[SCOI2009]windy数 题解动态规划DP

[SCOI2009]windy数

Time Limit:1000MS  Memory Limit:165536K
Total Submit:162 Accepted:74

Description

windy定义了一种windy数。
不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。
windy想知道,在A和B之间,包括A和B,总共有多少个windy数?

Input

包含两个整数,A B。

Output

一个整数。

Sample Input

【输入样例一】
1 10

【输入样例二】
25 50

 

Sample Output

【输出样例一】
9

【输出样例二】
20

【数据规模和约定】
20%的数据,满足 1 <= A <= B <= 1000000 。
100%的数据,满足 1 <= A <= B <= 2000000000 。

 

Source

Day1

 

http://61.187.179.132:8080/JudgeOnline/showproblem?problem_id=1026

 

 

 

状态:

令d[i][j]代表i位数,其中最高位为j的Windy数个数

 

状态转移方程:


d[i][j]=∑d[i-1][k](0≤k≤9且|k-j|≥2

 

边界:

d[1][j]=j

 

代码:

/* 令d[i][j]代表i位数,其中最高位为j的Windy数个数: d[i][j]=∑d[i-1][k](0≤k≤9且|k-j|≥2) */ #include<cstdio> #include<cstdlib> int i,j,k,d[20][10],t[]={0,1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,-1u>>1}; void dp() { for(i=0;i<=9;i++) d[1][i]=1; for(i=2;i<=9;i++) for(j=0;j<=9;j++) for(k=0;k<=9;k++) if(abs(j-k)>=2) d[i][j]+=d[i-1][k]; for(j=1;j<3;j++) for(k=0;k<=9;k++) if(abs(j-k)>=2) d[10][j]+=d[9][k]; } int find(int n) { int i,j,k=1,num,last,ans=0; while(t[k]<=n)k++; k--; for(i=1;i<k;i++) for(j=1;j<=9;j++) ans+=d[i][j]; num=n/t[k]; for(j=1;j<num;j++) ans+=d[k][j]; n%=t[k]; last=num; for(i=k-1;i>0;i--) { num=n/t[i]; for(j=0;j<num;j++) if(abs(last-j)>=2) ans+=d[i][j]; if(abs(num-last)<2) break; last=num; n%=t[i]; } return ans; } int main() { dp(); int a,b; scanf("%d%d",&a,&b); printf("%d/n",find(b+1)-find(a)); }

你可能感兴趣的:(input,output)