关于数位dp
上周学了数位dp,本来想上周周末写一下这个总结,怎奈没有安排上时间
安排 @TOC
关于题目小结
关于所做过题目的总结以及一些个人想法。
不要62 HDU - 2089
这个题目给我的收获是知道怎么去处理出现连续的两个位数和出现单个位数的特殊情况。
对于这种连续两个位数的情况直接使ispre是上一位是x,i是下一位。
单个位数的话限制条件就是i。
然后,直接上模板做就可以了。比如这题。
HDU - 3555 Bomb
还有这个题目
HDU - 3652
关于这道题目限制条件就是出现13和数不能被13整除的个数。
又get了一个新的知识,就是对于被某个数整除的情况,
对于被整除, modx=mod*10+i;//这个可以求出每一个数字。
简单
说到着,这些数位dp简单题目学了数位dp的人肯定都可以做,因为(这个dp的束缚条件比较少,也比较好处理。)
我不想就仅仅如此,我还想更上一层楼,那么对于这个,还需要自己做更多的题目。
ll dfs(int pos,int mod,int have,int limit)
{
int modx,havex;
if(pos==0)
{
return mod==0&&have==2;
}
if(!limit&&dp[pos][mod][have]!=-1)
return dp[pos][mod][have];
ll ans=0;
int Max=limit?num[pos]:9;
for(ll i=0; i<=Max; i++)
{
modx=(mod*10+i)%13;//关于位数
havex=have;
if(have==0&&i==1)
havex=1;
if(have==1&&i!=1)
havex=0;
if(have==1&&i==3)
havex=2;
ans+=dfs(pos-1,modx,havex,(limit&&i==Max));
}
if(!limit)
dp[pos][mod][have]=ans;
return ans;
}
简单比如这道题
追梦之人
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
ll dp[500][9000][3];
ll num[50];
ll dfs(int pos,ll mod,int have,int limit)
{
ll modx;
if(pos==0)
{
return mod%7!=0;
}
if(!limit&&dp[pos][mod][have]!=-1)
return dp[pos][mod][have];
ll ans=0;
int Max=limit?num[pos]:9;
for(int i=0; i<=Max; i++)
{
modx=(mod*10+i)%7;
if(i==7)
continue;
ans+=dfs(pos-1,modx,i==7,(limit&&i==Max));
}
if(!limit)
dp[pos][mod][have]=ans;
return ans;
}
ll jj(ll x)
{
int cnt=0;
while(x)
{
num[++cnt]=x%10;
x/=10;
}
return dfs(cnt,0,1,1);
}
int main()
{
ll a;
int t;
cin>>t;
memset(dp,-1,sizeof(dp));
while(t--)
{
scanf("%lld",&a);
printf("%lld\n",jj(a));
}
return 0;
}
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
int dp[18][2][2];
int num[18];
int dfs(int pos,int ispre,int limit)
{
if(pos==0)
return 1;
if(dp[pos][ispre][limit]!=-1)
{
return dp[pos][ispre][limit];
}
int sum=0;
int up=limit?num[pos]:9;
for(int i=0; i<=up; i++)
{
if(ispre&&i==2)
continue;
if(i==4)
continue;
sum+=dfs(pos-1,i==6,limit&&i==up);
}
return dp[pos][ispre][limit]=sum;
}
int solve(int x)
{
mem(dp,-1);
int pos=0;
while(x)
{
num[++pos]=x%10;
x/=10;
}
return dfs(pos,0,1);
}
int main()
{
int ri,le;
while(scanf("%d%d",&le,&ri)&&ri+le)
{
printf("%d\n",solve(ri)-solve(le-1));
}
return 0;
}