BZOJ_1026_[SCOI2009]windy数_数位DP
2018-02-21 19:26
288 查看
BZOJ_1026_[SCOI2009]windy数_数位DP
题意:windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,
在A和B之间,包括A和B,总共有多少个windy数?
学一下数位DP。
f[i][j]表示i位数以j开头的windy数个数。转移有f[i+1][k]+=f[i][j](abs(j-k)>=2)
答案转成[1~R]-[1~L-1]之后按位枚举,每次枚举到当前位上的数减1。
注意:
1.枚举到两位差2以内时停止枚举。
2.答案要加上位数比他小的所有windy数。
代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int f[15][15],a,b; int c[15],d[15]; int sol(int x){ int num=x,cnt=0,ans=0; while(num){ c[++cnt]=num%10; num/=10; }for(int i=1;i<=cnt;i++)d[i]=c[cnt-i+1]; for(int i=1;i<cnt;i++) for(int j=1;j<=9;j++)ans+=f[i][j]; for(int i=1;i<d[1];i++)ans+=f[cnt][i]; for(int i=2;i<=cnt;i++){ for(int j=0;j<d[i];j++){ if(d[i-1]-j<2&&j-d[i-1]<2)continue; ans+=f[cnt-i+1][j]; } if(d[i-1]-d[i]<2&&d[i]-d[i-1]<2)break; } return ans; } int main(){ 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(k-j<2&&j-k<2)continue; f[i][j]+=f[i-1][k]; } } } scanf("%d%d",&a,&b); //sol(18717); printf("%d\n",sol(b+1)-sol(a)); } /* 18716 38434 5178*/
相关文章推荐
- bzoj1026: [SCOI2009]windy数 [简单数位dp]
- bzoj 1026 [SCOI2009]windy数 数位dp
- 【BZOJ】1026: [SCOI2009]windy数 数位DP
- [SCOI 2009]BZOJ 1026 windy数 - 数位dp
- BZOJ 1026 [SCOI2009]windy数【数位DP】
- bzoj 1026: [SCOI2009]windy数(数位dp)
- 【bzoj1026】[SCOI2009]windy数 数位dp
- BZOJ_1026_[SCOI2009]_windy数_(数位dp)
- [BZOJ1026][SCOI2009]windy数(数位dp)
- bzoj:1026: [SCOI2009]windy数(数位dp)
- 【BZOJ】1026 [SCOI2009]windy数 数位dp
- 【BZOJ1026】【SCOI2009】windy数 数位DP
- [BZOJ1026][SCOI2009]windy数 && 数位DP
- 【数位DP】bzoj1026: [SCOI2009]windy数
- BZOJ 1026 [SCOI2009]windy数 数位dp
- bzoj1026 [SCOI2009]windy数(数位dp)
- 【数位DP】bzoj1026: [SCOI2009]windy数
- bzoj1026 [SCOI2009]windy数(数位dp)
- 【BZOJ】1026: [SCOI2009]windy数(数位dp)
- bzoj1026: [SCOI2009]windy数 数位dp