您的位置:首页 > 其它

(hdu 2089 不要62)<基础数位DP>

2017-08-11 17:40 357 查看
传送门

Solution

显然暴力是会出滑稽的

f[i][j]表示共有i位,其中最高位为j的数的个数

状态转移:

f[i,j]代表开头是j的i位数中不含”62”或”4”的数有几个。

如f[2,6]包含60,61,63,65,66,67,68,69

f[0,0]=1;

for(i=1 7)

for(j=0 9)//枚举第i位

for(k=0 9)//枚举第i−1位

ifj<>4||(j=6andk=2)continue;

f[i,j]=f[i−1,k]+f[i,j];

关于统计答案:

先预处理出数字x每一位的数字是几,d[1]保存个位,d[2]保存十位,依次类推

注意f数组的含义是有i位的数字的数的个数,而不是前i位的所有情况

因此从高位开始枚举每i位中比d[i]小的数,加入答案

当第i位出现4或者与更高的位上的数字组成62的情况时,停止统计

最后的答案是solve(m+1)-solve(n),

Code

// by spli
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define LL long long
using namespace std;

int n,m;
LL f[7][10];
int d[10];

LL solve(int p){
LL ret=0;
int k=0;
while(p){
d[++k]=p%10;
p/=10;
}
d[k+1]=0;
for(int i=k;i>=1;--i){
for(int j=d[i]-1;j>=0;--j)
if(d[i+1]!=6||j!=2)
ret+=f[i][j];
if(d[i]==4||(d[i+1]==6&&d[i]==2)) break;
}
return ret;
}

int main(){
for(int i=0;i<=9;++i)
if(i!=4) f[1][i]=1;
for(int i=2;i<=7;++i)
for(int j=0;j<=9;++j)
if(j!=4)
for(int k=0;k<=9;++k){
if(k==2&&j==6) continue;
f[i][j]+=f[i-1][k];
}
while(scanf("%d%d",&n,&m)&&(n+m)){
printf("%lld\n",solve(m+1)-solve(n));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: