记忆化搜索的专题

题解在代码中

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 数位动态规划的更多相关文章

  1. YBT 5.2 树形动态规划

    题解在代码中 二叉苹果树[loj 10153] /* 若要留q条边便是要留q+1个点 所以记忆化搜索 dp[pos][ans]=max(dp[pos][ans],dp[l[pos]][k]+dp[r[ ...

  2. [题解+总结]动态规划大合集II

    1.前言 大合集总共14道题,出自江哥之手(这就没什么好戏了),做得让人花枝乱颤.虽说大部分是NOIP难度,也有简单的几道题目,但是还是做的很辛苦,有几道题几乎没思路,下面一道道边看边分析一下. 2. ...

  3. 数位dp 的简单入门

    时间紧张,就不讲那么详细了. 之前一直被深搜代码误解,以为数位dp 其实就是记忆化深搜...(虽说爆搜确实很舒服而且还好想) 但是后来发现数位dp 的标准格式其实是 预处理 + dp ...... 数 ...

  4. 『嗨威说』算法设计与分析 - 动态规划思想小结(HDU 4283 You Are the One)

    本文索引目录: 一.动态规划的基本思想 二.数字三角形.最大子段和(PTA)递归方程 三.一道区间动态规划题点拨升华动态规划思想 四.结对编程情况 一.动态规划的基本思想: 1.1 基本概念: 动态规 ...

  5. 动态规划大合集II

    1.前言 大合集总共14道题,出自江哥之手(这就没什么好戏了),做得让人花枝乱颤.虽说大部分是NOIP难度,也有简单的几道题目,但是还是做的很辛苦,有几道题几乎没思路,下面一道道边看边分析一下. 2. ...

  6. OI省选算法汇总

    copy from hzwer @http://hzwer.com/1234.html 侵删 1.1 基本数据结构 1. 数组 2. 链表,双向链表 3. 队列,单调队列,双端队列 4. 栈,单调栈 ...

  7. hdu_3555 bomb

    数位动态规划     数位动态规划是求解一个大区间[L, R]中间满足条件Q的所有数字的个数(或者和,或其他)的一种方法.它通过分析每一位上的数字,一般用 dp[len][digit][...] 来表 ...

  8. hdu_2089 不要62

    数位动态规划     数位动态规划是求解一个大区间[L, R]中间满足条件Q的所有数字的个数(或者和,或其他)的一种方法.它通过分析每一位上的数字,一般用 dp[len][digit][...] 来表 ...

  9. Careercup - Google面试题 - 4857362737266688

    2014-05-04 00:10 题目链接 原题: Write a function return an integer that satisfies the following conditions ...

随机推荐

  1. 一步一步图文介绍SpriteKit使用TexturePacker导出的纹理集Altas

    1.为什么要使用纹理集? 游戏是一种很耗费资源的应用,特别是在移动设备中的游戏,性能优化是非常重要的 纹理集是将多张小图合成一张大图,使用纹理集有以下优点: 1.减少内存占用,减少磁盘占用: 2.减少 ...

  2. lintcode: Check Sum of Square Numbers

    Check Sum of Square Numbers Given a integer c, your task is to decide whether there're two integers ...

  3. Click Once使用总结

    做了一个CS结构软件,有十几个用户使用的客户端,因为刚开始试用期间,要不断根据用户使用情况修正问题和添加新功能,所以频繁更新是不可避免的,暂时没有深入去研究软件更新,暂时采取的方式是用户通过FTP自行 ...

  4. HPUX 11.31 MC/SG恢复丢失的锁盘

    有时候由于一些特殊的原因,用户的cluster中的锁盘信息丢失,或者需要更换锁盘,只要执行一个命令就可以了. #cmdisklock reset /dev/vglock:/dev/disk/diskX ...

  5. ZOJ 3689 Digging(DP)

    Description When it comes to the Maya Civilization, we can quickly remind of a term called the end o ...

  6. how to install pygraphviz on windows 10 with python 3.6

    Here's what worked for me: Win 7 AMD64 Install MSFT C++ compiler. Install Anaconda for Win AMD64, Py ...

  7. HashCode和equals的理解

    -------------------------------------------------------------------------------------------第一篇博客---- ...

  8. VS2013 “未找到与约束 ContractName Microsoft.Internal.VisualStudio.PlatformUI.ISolutionAttachedCollectionService RequiredTypeIdentity Microsoft.Internal.VisualStudio.PlatformUI.ISolutionAttachedCollectionService 匹配的导出”

    下面是我出错误的附加图片 这个错误导致无法打开项目. 解决方法: 解: C:\Users\Administrator\AppData\Local\Microsoft\VisualStudio\12.0 ...

  9. lol佐伊美图

      心血来潮,分享一波从各个网站上搜集到的佐伊美图,持续更新!(最近更新日期:2019/03/17) Section1 暮光星灵 2018/11/16 2019/02/15 2019/03/17 Se ...

  10. 【week6】用户数

    小组名称:nice! 小组成员:李权 于淼 杨柳 刘芳芳 项目内容:约跑app alpha发布48小时以后用户数如何,是否达到预期目标,为什么,是否需要改进,如何改进(或理性估算). 首先我们的app ...