您的位置:首页 > 其它

hdu 3555 含有49的数 数位dp

2016-03-13 17:22 281 查看
题目:

http://acm.hdu.edu.cn/showproblem.php?pid=3555

题意:

给定任意n,计算从1~n中有多少数包含49

分析:

今天看到群里有个人问这道题,我就做了一下,dfs就搞定了。。看了一下题解,大部分是递推,找规律求解。但是做题还是dfs

#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
ll f[20][3]; //依次表示当前位不是4且不含49,是4,有了49.这三个状态
int s[20];
ll dfs(int pos,int is,bool lim)
{
if(pos<=0)return is==2;
if(!lim&&f[pos][is]!=-1)return f[pos][is];
int num=lim?s[pos]:9;
ll ans=0;
for(int i=0;i<=num;i++){
int iis=0;
if(is==2)iis=2;
else if(is==1&&i==9)iis=2;
else if(i==4)iis=1;

ans+=dfs(pos-1,iis,lim&&i==num);
}
if(!lim)f[pos][is]=ans;
return ans;
}
int main()
{
memset(f,-1,sizeof(f));
int T,n;
cin>>T;
while(T--){
ll n;
cin>>n;
int len=0;
while(n){
s[++len]=n%10;
n/=10;
}
// for(int i=0;i<=len;i++)cout<<s[i];
// cout<<endl;
cout<<dfs(len,0,1)<<endl;
}
return 0;
}
递推:

偷点懒,copy点别人写的:http://www.cnblogs.com/sjy123/p/3247731.html

dp[i][0]=dp[i-1][0]*10-dp[i-1][1];                         //代表不含49 (当位数增加一位,不含49的数增加10倍,但是要减去一个以9开头的)

dp[i][1]=dp[i-1][0];                                             //代表不含49,但以9开头(当位数增加一位,就增长了在原来不以9开头的那些)

dp[i][2]=dp[i-1][2]*10+dp[i-1][1];                       //代表包含49(当位数增加一位,之前已经包含49的增加10倍,另外要加上现在开头为4和之前开头为9组合成49的数)

当然状态转移方程不止这一种,如:

 

dp[k][0]=dp[k-1][0]*9+dp[k-1][1]*8;                   //dp[][0]表示不包含49并且以非4结尾的个数

dp[k][1]=dp[k-1][0]+dp[k-1][1];                          //dp[][1]表示不包含49并且以4结尾的个数

dp[k][2]=dp[k-1][1]+dp[k-1][2]*10;                     //dp[][2]表示包含49的个数

#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
ll f[20][3];
int s[20];
void init()
{
f[0][0]=1;
f[0][1]=0;
f[0][2]=0;
for(int i=1;i<20;i++){
f[i][0]=f[i-1][0]*10-f[i-1][1];
f[i][1]=f[i-1][0];
f[i][2]=f[i-1][1]+f[i-1][2]*10;
}
}
int main()
{
init();
int T,n;
cin>>T;
while(T--){
ll n;
cin>>n;
int len=0;
n++;
while(n){
s[++len]=n%10;
n/=10;
}
bool flag=0;
ll ans=0;
s[len+1]=0;
for(int i=len;i>0;i--){
ans+=f[i-1][2]*s[i];
if(flag)ans+=f[i-1][0]*s[i];
if(!flag&&s[i]>4)ans+=f[i-1][1];
if(s[i+1]==4&&s[i]==9)flag=1;
}
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: