世界真的很大
学了一小会儿数位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
*/
嗯,就是这样