一本通1586【 例 2】数字游戏
1586:【 例 2】数字游戏
时间限制: 1000 ms 内存限制: 524288 KB
题目描述
科协里最近很流行数字游戏。某人命名了一种不降数,这种数字必须满足从左到右各位数字成小于等于的关系,如 123,446。现在大家决定玩一个游戏,指定一个整数闭区间 [a,b],问这个区间内有多少个不降数。
输入格式
有多组测试数据。每组只含两个数字 a,b,意义如题目描述。
输出格式
每行给出一个测试数据的答案,即 [a, b] 之间有多少不降数。
样例
样例输入
1 9
1 19
样例输出
9
18
数据范围与提示
对于全部数据,1≤a≤b≤2^31−1。
sol:非常友好的数位dp,dp[i][j][bo1][bo2] 第i位,填的数字为j,是否是上界,是否是前导0
暴力统计+暴力转移就OK了
#include <bits/stdc++.h> using namespace std; int Num[20]; int dp[20][10][2][2]; //第i位,数字为j,是否为上界,是否为前导0 inline int dfs(int Weiz,int Shuz,bool Shangj,bool Qiand0) { if(dp[Weiz][Shuz][Shangj][Qiand0]) return dp[Weiz][Shuz][Shangj][Qiand0]; if(Weiz==1) return (dp[Weiz][Shuz][Shangj][Qiand0]=1); int i,Down=(Qiand0)?(0):(Shuz),Up=(Qiand0)?(9):(Shangj?Num[Weiz-1]:9); // printf("Down=%d Up=%d\n",Down,Up); for(i=Down;i<=Up;i++) { bool Bo1=(Shangj&&i==Up),Bo2=(Qiand0&&i==0); dp[Weiz][Shuz][Shangj][Qiand0]+=dfs(Weiz-1,i,Bo1,Bo2); } return dp[Weiz][Shuz][Shangj][Qiand0]; } inline int Solve(int n) { if(n==0) return 1; *Num=0; while(n) { Num[++*Num]=n%10; n/=10; } int i,ans=0; ans+=dfs(*Num,0,0,1); // printf("Beg ans=%d\n",ans); for(i=1;i<Num[*Num];i++) ans+=dfs(*Num,i,0,0); // printf("End ans=%d\n",ans); ans+=dfs(*Num,Num[*Num],1,0); // printf("ans=%d\n",ans); memset(dp,0,sizeof dp); return ans; } int main() { // freopen("test1.in","r",stdin); // freopen("my.out","w",stdout); int i,l,r; while(~scanf("%d%d",&l,&r)) { printf("%d\n",Solve(r)-Solve(l-1)); } } /* input 1 9 1 19 3601 152425051 output 9 18 36116 */
河田は河田、赤木は赤木……。
私は誰ですか。教えてください、私は誰ですか。
そうだ、俺はあきらめない男、三井寿だ!