您的位置:首页 > 其它

hdu 3555 Bomb 经典数位DP

2016-08-22 22:25 288 查看
传送门:Bomb

题目大意

给定一个整数N,求1~N中连续49的个数

解题思路

dp[i][0]表示长度为i位,不包含49的个数

dp[i][1]表示长度为i位,第一位是9的个数

dp[i][2]表示长度为i位,包含49的个数

AC代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
#include <iostream>
using namespace std;
typedef unsigned long long ULL;
const int MX = 69;
const int INF = 0x3f3f3f3f;
__int64 dp[MX][MX];

void init()
{
memset(dp,0,sizeof dp);
dp[0][0] = 1;
for(int i=1; i<MX; i++)
{
dp[i][0] = dp[i-1][0]*10 - dp[i-1][1];//最高位有⑩种可能,但是要减去49开头的
dp[i][1] = dp[i-1][0];//最开头是9后面的所有位不固定
dp[i][2] = dp[i-1][2]*10 + dp[i-1][1];//前i-1位中包含49的并且加上i-1位中9开头的
}
}

__int64 solve(__int64 n)
{
int len = 0,digit[MX],flag = 0;
__int64 ans=0;
while(n)
{
digit[++len] = n%10;
n/=10;
}
digit[len+1] = 0;
for(int i=len; i; i--)
{
ans+=dp[i-1][2]*digit[i];
if(flag)  ans+=dp[i-1][0]*digit[i];
if(!flag && digit[i]>4) ans += dp[i-1][1];
if(digit[i+1]==4&&digit[i]==9) flag = 1;
}
return ans;
}
int main()
{
__int64 T,N;
init();
cin>>T;
while(T--)
{
cin>>N;
cout<<solve(N+1)<<endl;
}
return 0;
}


使用DFS的方式

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int MX = 66;
__int64 dp[MX][MX][MX],digit[MX];

__int64 DFS(int pos,bool have,int last,int limit)
{
if(pos==-1) return have;
if(!limit && dp[pos][have][last]!=-1) return dp[pos][have][last];
int endP = limit?digit[pos]:9;
__int64 ans=0;
for(int i=0;i<=endP;i++){
if(last==4&&i==9) ans+=DFS(pos-1,true,i,limit&&(i==endP));
else ans+=DFS(pos-1,have,i,limit&&(i==endP));
}
if(!limit) dp[pos][have][last] = ans;
return ans;
}
__int64 solve(__int64 n)
{
int len = 0;
while(n){
digit[++len] = n%10;
n/=10;
}
return DFS(len,false,0,1);
}
int main()
{
__int64 N;
int T;
cin>>T;
while(T--){
memset(dp,-1,sizeof dp);
cin>>N;
cout<<solve(N)<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: