BZOJ 1026: [SCOI2009]windy数 (数位dp)
1026: [SCOI2009] windy数##
Time Limit: 1 Sec
Memory Limit: 162 MBDescription###
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 >windy想知道,在A和B之间,包括A和B,总共有多少个windy数?
Input###
包含两个整数,A B。
Output###
一个整数
Sample Input 1###
1 10
Sample Output 1###
9
HINT###
100%的数据,满足 1 <= A <= B <= 2000000000 。
题目地址: BZOJ 1026:[SCOI2009]windy数
题解:
裸的数位dp
第一次写QAQ,不会01的
www.cnblogs.com/AGFghy/
AC代码
#include<cstdio>
#include<algorithm>
typedef long long ll;
ll a,b;
ll p[20],f[20][15];
ll solve(ll x)
{
if (x==0) return 0;
ll y,ans=0,sw,pre;
sw=1;
while (p[sw]<=x) sw++;
sw--;
for (int i=1; i<=sw-1; i++)
for (int j=1; j<=9; j++)
ans+=f[i][j];
y=x/p[sw];
for (int i=1; i<y; i++)
ans+=f[sw][i];
x=x%p[sw];
pre=y;
sw--;
while (sw>0)
{
y=x/p[sw];
for (int i=0; i<y; i++)
if (abs(pre-i)>=2) ans+=f[sw][i];
if (sw==1)
if (abs(pre-y)>=2) ans+=f[sw][y];
if (abs(y-pre)<2) break;
x=x%p[sw];
pre=y;
sw--;
}
return ans;
}
int main()
{
scanf("%lld%lld",&a,&b);
p[1]=1;
for (int i=2; i<=12; i++)
p[i]=p[i-1]*10;
for (int i=0; i<=9; i++)
f[1][i]=1;
for (int i=2; i<=10; i++)
for (int j=0; j<=9; j++)
for (int k=0; k<=9; k++)
if (abs(j-k)>=2) f[i][j]+=f[i-1][k];
printf("%lld\n",solve(b)-solve(a-1));
return 0;
}