BZOJ 1026 [SCOI2009]windy数
1026: [SCOI2009]windy数
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3700 Solved: 1662
[Submit][Status][Discuss]
Description
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?
Input
包含两个整数,A B。
Output
一个整数。
Sample Input
【输入样例一】
1 10
【输入样例二】
25 50
1 10
【输入样例二】
25 50
Sample Output
【输出样例一】
9
【输出样例二】
20
9
【输出样例二】
20
HINT
【数据规模和约定】
100%的数据,满足 1 <= A <= B <= 2000000000 。
Source
题解:妈妈呀,上来以为这是一道神级数学题,于是就被坑了。。。
一开始想过前缀爆搜,但是觉得会不会太简单了。。。(捂脸。。。
我是设dfs(x,d,tp,fch)表示第d个数字是x的满足题意的数字的个数,tp表示借位。。。呃。。。前置0.。。。(意会意会。。。我找不到更好的词了。。。),fch表示是否是开头。
然后窝萌记忆化一下就不会T了,细节貌似还挺多。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar('\n') 9 using namespace std; 10 int a[12],dp[15][12],sz; 11 int dfs(int x,int d,int tp,int fch){ 12 if(!d)return 1; 13 if(dp[x][d]!=-1&&!tp) return dp[x][d]; 14 int res=0,from=0,to=9; 15 if(fch)from=1;if(tp)to=a[d]; 16 for(int i=from;i<=to;i++){ 17 if(abs(x-i)>1){ 18 if(tp&&i==to)res+=dfs(i,d-1,1,0); 19 else res+=dfs(i,d-1,0,0); 20 } 21 }if(!tp)dp[x][d]=res;return res; 22 } 23 int solve(int n){ 24 memset(dp,-1,sizeof(dp));if(!n) return 0; 25 sz=0;int x=n; 26 while(x){sz++;a[sz]=x%10;x/=10;} 27 int ans=0; 28 for(int i=1;i<sz;i++)ans+=dfs(11,i,0,1); 29 return ans+dfs(11,sz,1,1); 30 } 31 inline int read(){ 32 int x=0,sig=1;char ch=getchar(); 33 while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();} 34 while(isdigit(ch))x=10*x+ch-'0',ch=getchar(); 35 return x*=sig; 36 } 37 inline void write(int x){ 38 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 39 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 40 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 41 } 42 int n,m; 43 void init(){ 44 n=read();m=read(); 45 write(solve(m)-solve(n-1)); 46 return; 47 } 48 void work(){ 49 return; 50 } 51 void print(){ 52 return; 53 } 54 int main(){init();work();print();return 0;}