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;
}
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;
}
相关文章推荐
- 深入理解position: fixed
- BC #75 hdu 5642 数位dp/ 递推
- SimpleAdapter创建ListView
- BZOJ 3997 TJOI2015 组合数学
- cocos2d-x 解决win32下 从文件对话框选择文件,显示在游戏中乱码的问题
- JDK安装出现1335错误
- html5结构化标签
- android获取今天00:00时间戳的方法
- Facebook的手游出海之道
- sass学习--什么是sass
- 构建之法阅读笔记02
- parted 用法
- 九度题目1138进制转换
- Android中的一些基础知识(二)
- 我也读读从0到1
- Android学习资源网站大全
- prim求最小生成树——Highways
- 构建之法阅读笔记01
- KMP
- 命令上执上执行Yaf