您的位置:首页 > 其它

HDU 3555 浅谈数位动态规划逆向计数问题练习

2017-09-22 17:27 691 查看


世界真的很大

学了一小会儿数位DP,自然要找一点题来练

还是要融汇贯通才好

找到新题与原题之间的联系,辅助解题

看题先:

description:

题意就是找0到n有多少个数中含有49。数据范围接近10^20


input:

第一行一个整数T
接下来T行,每行一个整数n


output:

T行。
每行一个整数表示答案


这道题

首先dfs转移里面,需要包含前面出没出现49,上一位是什么

要考虑出没出现49,出现了几次49。。

头大。。

可能是我蠢吧

然后灵光一现,出现了49不就是总数减去没有出现49吗

这个思路类比:BZOJ 3556

然后嘛,至于求没有出现49的数,只需要保证在任何时候都不出现49就行了

这个类比 HDU 2089

这个写起来就很简单了

只需要存一下上一位是什么就行了

完整代码:

#include<stdio.h>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long dnt;

dnt f[20][20];
int a[20],T;

dnt dfs(int pos,int pre,int lim)
{
dnt ans=0;
if(pos==-1) return 1;
if(!lim && f[pos][pre]!=-1) return f[pos][pre];
int up=lim ? a[pos] : 9;
for(int i=0;i<=up;i++)
{
if(pre==4 && i==9) continue;
ans+=dfs(pos-1,i,lim && i==up);
}
if(!lim) f[pos][pre]=ans;
return ans;
}

dnt solve(dnt n)
{
int cnt=0;
dnt tmp=n;
memset(a,0,sizeof(a));
while(n)
{
a[cnt++]=n%10;
n/=10;
}
return tmp+1-dfs(cnt-1,0,1);
}

int main()
{
scanf("%d",&T);
memset(f,-1,sizeof(f));
while(T--)
{
dnt n;
cin >> n;
cout << solve(n) << endl;
}
return 0;
}
/*
EL PSY CONGROO
*/


嗯,就是这样
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: