1026: [SCOI2009]windy数
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 6026 Solved: 2690
[ 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
题解:数位dp
f[i][j][0/1][0/1][0/1]填到第i位数字为j,是否卡上限,是否卡下线,是否1-(i-1)位前导零的方案总数。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define N 20 using namespace std; int n,m,a1[N],b1[N],f[N][N][3][3][3],cnt,ans; int main() { scanf("%d%d",&n,&m); cnt=0; while (m) { a1[++cnt]=m%10; m/=10; } for (int i=cnt;i>=1;i--) b1[cnt-i+1]=a1[i],a1[i]=0; int t=0; while (n) { t++; a1[cnt-t+1]=n%10; n/=10; } for (int i=a1[1];i<=b1[1];i++) f[1][i][i==a1[1]?1:0][i==b1[1]?1:0][i==0?1:0]=1; for (int i=1;i<cnt;i++) for (int j=0;j<=9;j++) for (int a=0;a<=1;a++) for (int b=0;b<=1;b++) for (int c=0;c<=1;c++) if (f[i][j][a][b][c]) { //cout<<i<<" "<<j<<" "<<a<<" "<<b<<" "<<c<<endl; if (a&&b) { if (c) { for (int k=a1[i+1];k<=b1[i+1];k++) f[i+1][k][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][a][b][c]; continue; } for (int k=a1[i+1];k<=b1[i+1];k++) { if (k==j||k==j-1||k==j+1) continue; f[i+1][k][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][a][b][c]; } } else if (!a&&!b) { if (c) { for (int k=0;k<=9;k++) f[i+1][k][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][a][b][c]; continue; } for (int k=0;k<=9;k++) { if (k==j||k==j-1||k==j+1) continue; f[i+1][k][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][a][b][c&k]; } } else if (!a) { if (c) { for (int k=0;k<=b1[i+1];k++) f[i+1][k][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][a][b][c]; continue; } //if (j-2>b1[i+1]) continue; for (int k=0;k<=b1[i+1];k++) { if (k==j||k==j-1||k==j+1) continue; f[i+1][k][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][a][b][c]; } } else { if (c) { for (int k=a1[i+1];k<=9;k++) f[i+1][k][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][a][b][c]; continue; } for (int k=a1[i+1];k<=9;k++) { if (k==j||k==j-1||k==j+1) continue; f[i+1][k][a&(k==a1[i+1]?1:0)][b&(k==b1[i+1]?1:0)][c&(k==0?1:0)]+=f[i][j][a][b][c]; } } } for (int i=0;i<=9;i++) for (int a=0;a<=1;a++) for (int b=0;b<=1;b++) for (int c=0;c<=1;c++) ans+=f[cnt][i][a][b][c]; printf("%d\n",ans); }