YBT 5.3 数位动态规划
记忆化搜索的专题
题解在代码中
Amount of Degrees[loj 10163]
/*
此题可以转换成将10进制转成b进制后有k个1其他都为0的个数
所以用记忆化dfs
dp[pos][sum]表示将要处理第pos位,前面已有sum个一的数量
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
int x,y,k,b,dg[],ans,dp[][];
long long dfs(long long pos,long long sum,long long done,long long sry)
{
// cout<<"位置:"<<pos<<" 一的个数:"<<sum<<" 小于等于:"<<done<<" 原来的数:"<<sry<<endl;
if(sum>k) return ;
if(pos==)
{
if(sum==k) return ;
return ;
}
if(done==&&dp[pos][sum]!=-) return dp[pos][sum];
long long end;
if(done==) end=;
else end=min(,dg[pos]);
long long maxn=;
for(long long i=;i<=end;i++)
{
if(i==) maxn+=dfs(pos-,sum+,done&&i==dg[pos],i);
else maxn+=dfs(pos-,sum,done&&i==dg[pos],i);
}
if(done==) dp[pos][sum]=maxn;
return maxn;
}
long long solve(long long x)
{
ans=;memset(dg,,sizeof(dg));
while(x!=)
{
dg[++ans]=x%b;
x/=b;
}
// for(long long i=ans;i>=1;i--) cout<<dg[i]<<" ";
// cout<<endl;
return dfs(ans,,,<<-);
}
int main()
{
memset(dp,-,sizeof(dp));
x=read(),y=read(),k=read(),b=read();
cout<<solve(y)-solve(x-);
}
数字游戏[loj 10164]
/*
记忆化dfs
dp[pos][sta]表示将要处理第pos位,上一位是sta的数量
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int dp[][],ans,dg[];
int dfs(int pos,int sta,int done)//done为是否与原数小于或相等
{
// cout<<pos<<" "<<sta<<" "<<done<<endl;
if(pos==) return ;
if(done==&&dp[pos][sta]!=-) return dp[pos][sta];
int end;
if(done==) end=;
else end=dg[pos];
// cout<<end<<endl;
int maxn=;
for(int i=sta;i<=end;i++)
maxn+=dfs(pos-,i,done&&i==dg[pos]);
if(done==) dp[pos][sta]=maxn;
return maxn;
}
int solve(int x)
{
ans=;
while(x!=)
{
dg[++ans]=x%;
x/=;
}
// cout<<ans<<endl;
// for(int i=ans;i>=1;i--) cout<<dg[i]<<" ";cout<<endl;
return dfs(ans,,);
}
int main()
{
memset(dp,-,sizeof(dp));
int a,b;
while(scanf("%d%d",&a,&b)!=EOF)
{
printf("%d\n",solve(b)-solve(a-));
// return 0;
}
return ;
}
/*
1 20
*/
Windy 数[loj 10165]
/*
注意前导0,将它转换成11即可,想一想为什么
dp[pos][sta],记忆化dfs
当前位数,上次的数字
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
long long dp[][];
long long dg[];
long long dfs(long long pos,long long sta,long long done)//若flag为0,没有出现真正位
{
// cout<<"位数:"<<pos<<" 所得位数:"<<sta<<" 与原数的大小:"<<done<<" 有没有真正的位"<<flag<<endl;
if(pos==) return ;
if(done==&&dp[pos][sta]!=-) return dp[pos][sta];
long long end;
if(done==) end=dg[pos];
else end=;
long long maxn=;
// dfs(ans,0,1,0)
//long long dfs(long long pos,long long sta,long long done,bool flag)//若flag为0,没有出现真正位
for(long long i=;i<=end;i++)
{
if(abs(i-sta)<) continue;
if(sta==&&i==) maxn+=dfs(pos-,,done&&i==end);
else maxn+=dfs(pos-,i,done&&i==dg[pos]);
}
if(done==) dp[pos][sta]=maxn;
return maxn;
}
long long solve(long long x)
{
memset(dg,,sizeof(dg));
long long ans=;
while(x!=)
{
dg[++ans]=x%;
x/=;
}
// for(long long i=ans;i>=1;i--) cout<<dg[i]<<" ";cout<<endl;
return dfs(ans,,);
}
int main()
{
memset(dp,-,sizeof(dp));
long long a=read(),b=read();
cout<<solve(b)-solve(a-);
int x;
// while(scanf("%d",&x)!=EOF) cout<<solve(x)<<endl;
// long long x=read();cout<<solve(x);
return ;
}
数字游戏[loj 10166]
/*
sum为mod n的和
记忆化dfs,dp[pos][sum],不解释
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
long long a,b,dg[],dp[][],mod;
long long dfs(long long pos,long long sta,long long done,long long sum)
{
// cout<<"位数:"<<pos<<" 此数:"<<sta<<" 是否小于等于:"<<done<<" 和:"<<sum<<endl;
if(pos==)
{
if(sum%mod==) return ;
else return ;
}
if(done==&&dp[pos][sum]!=-) return dp[pos][sum];
long long end;
if(done==) end=;
else if(done==) end=dg[pos];
long long maxn=;
for(long long i=;i<=end;i++)
{
maxn+=dfs(pos-,i,done&&i==dg[pos],(sum+i)%mod);
}
if(done==) dp[pos][sum]=maxn;
return maxn;
}
long long solve(long long x)
{
memset(dg,,sizeof(dg));
long long ans=;
while(x!=)
{
dg[++ans]=x%;
x/=;
}
return dfs(ans,,,);
}
int main()
{ while(cin>>a>>b>>mod)
{
memset(dp,-,sizeof(dp));
cout<<solve(b)-solve(a-)<<endl;
}
// a=read(),b=read(),mod=read(); }
/*
19 9
*/
不要 62[loj 10167]
/*
只要不让62,4进for循环即可
dp[pos][sta]
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int dg[],dp[][];
int dfs(int pos,int sta,int done,bool flag)
{
// cout<<pos<<" "<<sta<<" "<<done<<" "<<flag<<endl;
if(pos==) return ;
if(done==&&dp[pos][sta]!=-) return dp[pos][sta];
int end;
if(done==) end=;
if(done==) end=dg[pos];
int maxn=;
for(int i=;i<=end;i++)
{
if(i==) continue;
if(i==&&flag==true) continue;
if(i==) maxn+=dfs(pos-,i,done&&i==dg[pos],true);
else maxn+=dfs(pos-,i,done&&i==dg[pos],false);
}
if(done==) dp[pos][sta]=maxn;
return maxn;
}
int solve(int x)
{
memset(dg,,sizeof(dg));
int ans=;
while(x!=)
{
dg[++ans]=x%;
x/=;
}
// for(int i=ans;i>=1;i--) cout<<dg[i]<<" ";
// cout<<endl;
return dfs(ans,,,false);
}
int main()
{
memset(dp,-,sizeof(dp));
// int x=read();
// cout<<solve(x)<<endl;return 0;
while()
{
int a=read(),b=read();
if(a==&&b==) return ;
cout<<solve(b)-solve(a-)<<endl;
}
}
恨 7 不成妻[loj 10168]
/*
主要是求平方和,其他的都可以记忆化搜索实现
dp[pos][pre1][pre2]表示当前以pos位作为下一位,pre1记录数字和,pre2记录数字
(i+next)^2=i*i+2*i*next+next*next
而放眼望去,合并同类项后可的
(i+next)^2=i*i+2*i*(接下来的数字和)+(平方和)
所以搜索把每一个都记录下来即可
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
const long long mod=;
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
struct node{
long long cnt;//个数
long long sum;//和
long long sqsum;//平方和
}dp[][][];
long long p[];
long long dg[];
node dfs(long long pos,long long pre1,long long pre2,long long done)//pre1表示数字和,pre2表示数字
{
if(pos==-)
{
node tmp;
tmp.cnt=tmp.sqsum=tmp.sum=;
if(pre1!=&&pre2!=) tmp.cnt=;
return tmp;
}
if(done== && dp[pos][pre1][pre2].cnt!=-) return dp[pos][pre1][pre2];
long long end;
if(done==) end=;
if(done==) end=dg[pos];
node ans;
ans.cnt=ans.sqsum=ans.sum=;
for(long long i=;i<=end;i++)
{
if(i==) continue;
node tmp=dfs(pos-,(pre1+i)%,(pre2*+i)%,done&&i==dg[pos]);
ans.cnt+=tmp.cnt;
ans.cnt%=mod;
ans.sum+=(tmp.sum+((p[pos]*i%mod)%mod)*tmp.cnt%mod)%mod;
ans.sum%=mod;
ans.sqsum+=(tmp.sqsum+((*p[pos]%mod*i)%mod)*tmp.sum)%mod;
ans.sqsum%=mod; ans.sqsum+=((p[pos]%mod*p[pos]%mod)*(tmp.cnt)%mod*(i%mod*i%mod)%mod);
ans.sqsum%=mod;
}
if(done==) dp[pos][pre1][pre2]=ans;
return ans; }
long long solve(long long x)
{
long long anss=;
while(x!=)
{
dg[anss++]=x%;
x/=;
}
return dfs(anss-,,,).sqsum;
}
int main()
{
p[]=;
for(int i=;i<;i++)
p[i]=(p[i-]*)%mod;
for(int i=;i<;i++)
for(int j=;j<;j++)
for(int k=;k<;k++)
dp[i][j][k].cnt=-;
long long t=read(),l,r;
while(t--)
{
l=read();r=read();
printf("%d\n",(solve(r)-solve(l-)+mod)%mod);
}
}
/*
1
2065 7880
*/
数字计数[loj 10169]
/*
其实感觉跟例题1没有什么区别
只要再看看前导0即可
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
long long a,b,cur,dg[],dp[][];
long long dfs(long long pos,long long done ,long long zero,long long sum)
{
if(pos==) return sum;
if(done==&&zero==&&dp[pos][sum]!=-) return dp[pos][sum];
long long end;
if(done==) end=dg[pos];
else end=;
long long maxn=;
for(long long i=;i<=end;i++)
maxn+=dfs(pos-,done&&i==dg[pos],zero&&i==,sum+(cur==&&i==&&zero==||cur&&i==cur));
if(done==&&zero==) dp[pos][sum]=maxn;
return maxn;
}
long long solve(long long x)
{
memset(dp,-,sizeof(dp));
long long ans=;
while(x!=)
{
dg[++ans]=x%;
x/=;
}
return dfs(ans,,,);
}
int main()
{
a=read(),b=read();
for(cur=;cur<=;cur++)
cout<<solve(b)-solve(a-)<<" ";
}
YBT 5.3 数位动态规划的更多相关文章
- YBT 5.2 树形动态规划
题解在代码中 二叉苹果树[loj 10153] /* 若要留q条边便是要留q+1个点 所以记忆化搜索 dp[pos][ans]=max(dp[pos][ans],dp[l[pos]][k]+dp[r[ ...
- [题解+总结]动态规划大合集II
1.前言 大合集总共14道题,出自江哥之手(这就没什么好戏了),做得让人花枝乱颤.虽说大部分是NOIP难度,也有简单的几道题目,但是还是做的很辛苦,有几道题几乎没思路,下面一道道边看边分析一下. 2. ...
- 数位dp 的简单入门
时间紧张,就不讲那么详细了. 之前一直被深搜代码误解,以为数位dp 其实就是记忆化深搜...(虽说爆搜确实很舒服而且还好想) 但是后来发现数位dp 的标准格式其实是 预处理 + dp ...... 数 ...
- 『嗨威说』算法设计与分析 - 动态规划思想小结(HDU 4283 You Are the One)
本文索引目录: 一.动态规划的基本思想 二.数字三角形.最大子段和(PTA)递归方程 三.一道区间动态规划题点拨升华动态规划思想 四.结对编程情况 一.动态规划的基本思想: 1.1 基本概念: 动态规 ...
- 动态规划大合集II
1.前言 大合集总共14道题,出自江哥之手(这就没什么好戏了),做得让人花枝乱颤.虽说大部分是NOIP难度,也有简单的几道题目,但是还是做的很辛苦,有几道题几乎没思路,下面一道道边看边分析一下. 2. ...
- OI省选算法汇总
copy from hzwer @http://hzwer.com/1234.html 侵删 1.1 基本数据结构 1. 数组 2. 链表,双向链表 3. 队列,单调队列,双端队列 4. 栈,单调栈 ...
- hdu_3555 bomb
数位动态规划 数位动态规划是求解一个大区间[L, R]中间满足条件Q的所有数字的个数(或者和,或其他)的一种方法.它通过分析每一位上的数字,一般用 dp[len][digit][...] 来表 ...
- hdu_2089 不要62
数位动态规划 数位动态规划是求解一个大区间[L, R]中间满足条件Q的所有数字的个数(或者和,或其他)的一种方法.它通过分析每一位上的数字,一般用 dp[len][digit][...] 来表 ...
- Careercup - Google面试题 - 4857362737266688
2014-05-04 00:10 题目链接 原题: Write a function return an integer that satisfies the following conditions ...
随机推荐
- html div内第二行文字显示不下的时候才用省略号代替 css实现
有时候文字太多,但为了美观想要在第二行的时候才显示省略号,而不是第一行超出马上就出现省略号 下面是css代码: overflow:hidden;text-overflow: ellipsis;//显示 ...
- Jmeter使用之:高效组织接口自动化用例技巧
Jmeter怎么使用的文章多如牛毛,但怎么组织好测试用例,则几乎很难看到.在本文,我将把Jmeter下怎么组织测试用例的几点心得分享给大家,希望能给你一些帮助或启示. 1.善用“逻辑控制器”中的“简单 ...
- Unity Lighting - Lighting overview 照明概述
Lighting overview 照明概述 In order to calculate the shading of a 3D object, Unity needs to know the ...
- Python全栈 Web(边框、盒模型、背景)
原文地址 https://yq.aliyun.com/articles/634926 ......................................................... ...
- jQuery用unbind方法去掉hover事件及其他方法介绍
近日项目开发十分的繁忙,其中一个需求是实现响应式导航.(响应式的问题我们在css相关的博客中再交流) 大家都知道导航是需要下来菜单效果的,必然就会用到 jQuery的 hover() 方法.若是导航放 ...
- jmeter使用复习
多终端进程: 配置客户端远程的ip地址和port 在客户端jmeter安装目录的bin目录下,修改配置文件 jmeter.properties 默认的remote_hosts 的值:(将肉鸡的地址加入 ...
- array.some() 方法兼容ie8
在第 5 版时,some 被添加进 ECMA-262 标准:这样导致某些实现环境可能不支持它.你可以把下面的代码插入到脚本的开头来解决此问题,从而允许在那些没有原生支持它的实现环境中使用它.该算法是 ...
- windows编程入门最重要的
要入门 Windows 编程,最重要的不是阅读什么教材,使用什么工具,而是先必须把以下几个对于初学者来说非常容易困惑的重要概念搞清楚: 1. 文字的编码和字符集.这部分需要掌握 ANSI 模式和 Un ...
- java知乎爬虫
好久没写博客了,前阵子项目忙着上线,现在有点空闲,就把最近写的一个爬虫和大家分享下,统计结果放在了自己买的阿里云服务器上(点此查看效果),效果如下: 程序是在工作之余写的,用了java 的webmgi ...
- 搭建独立域名博客 -- 独立域名博客上线了 www.hanshuliang.com
博客是安装在阿里云的服务器上. 小结 : -- 进入数据库命令 :mysql -uroot -p123456 ; -- 检查nginx配置语法 :.../nginx/sbin/nginx -t; -- ...