bzoj1026SCOI2009windy数
Posted AaronPolaris
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1026SCOI2009windy数相关的知识,希望对你有一定的参考价值。
1026: [SCOI2009]windy数
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5345 Solved: 2402
[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 。
数位DP
f[i][j]表示以i开头长度为j的windy数的个数,然后从高位到低位随便搞搞就可以了。
注意第一位和最后一位特殊情况的判断。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long using namespace std; ll f[15][15],p[15]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline ll calc(int n) { if (!n) return 0; ll ret=0;int x=1,pre=1000,now; while (p[x]<=n) x++; F(i,1,x-1) F(j,1,9) ret+=f[j][i]; D(i,x,1) { now=n/p[i-1]; if (i==x){F(j,1,now-1) if (abs(pre-j)>=2) ret+=f[j][i];} else if (i==1){F(j,0,now) if (abs(pre-j)>=2) ret+=f[j][i];} else{F(j,0,now-1) if (abs(pre-j)>=2) ret+=f[j][i];} if (abs(pre-now)<2) break; pre=now; n%=p[i-1]; } return ret; } int main() { int a=read(),b=read(); p[0]=1;F(i,1,10) p[i]=p[i-1]*10; F(i,0,9) f[i][1]=1; F(i,2,10) F(j,0,9) F(k,0,9) if (abs(j-k)>=2) f[j][i]+=f[k][i-1]; printf("%lld\n",calc(b)-calc(a-1)); }
以上是关于bzoj1026SCOI2009windy数的主要内容,如果未能解决你的问题,请参考以下文章