【数位dp】求不超过n的数中,有多少个包含2018
程序员文章站
2022-06-17 14:54:34
...
【数位dp】求不超过n的数中,有多少个包含2018
n的范围是[0,1e9];
包含2018的意思是2018是该数的子序列,比如200176855,32018,5270168是符合条件的数, 2019,40017是不符合条件的数。
Sample Input
2018
Sample Input
1
Sample Input
20182018
Sample Input
92237
解题思路
数位dp ,记忆化搜索,从高位到低位,相当于是枚举所有的位,状态包括处理到第多少位,目前希望匹配的是什么(也就是希望得到2018中的哪个数),以及该位是否有限制(能不能取[0,9])
先数位分离,a[x]表示n的第x位,
dfs(x,nex,flag); //准备处理第x位,希望匹配到nex,flag==1表示有限制
根据flag和(nex与a[x]大小比较)来分类讨论,x位能填的数字无非是nex,a[x],其他普通的数三类。
AC代码
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const LL maxn=1e5+7;
char s[maxn];
int a[maxn];
int n;
int dp[11][11][2];
int mm[10];
int dfs(int x,int nex,int flag)
{
if(dp[x][nex][flag]!=-1) return dp[x][nex][flag];
int ans=0;
int y=9,res=0;
if(x>n)
{
if(nex==10) return 1;
else return 0;
}
if(flag)
{
if(a[x]==nex)
{
ans+=dfs(x+1,mm[nex],1);
ans+=a[x]*dfs(x+1,nex,0);
}
else if(a[x]<nex)
{
ans+=dfs(x+1,nex,1);
ans+=a[x]*dfs(x+1,nex,0);
}
else if(a[x]>nex)
{
ans+=dfs(x+1,mm[nex],0);
ans+=(a[x]-1)*dfs(x+1,nex,0);
ans+=dfs(x+1,nex,1);
}
}
else
{
if(nex==10)
{
ans+=10*dfs(x+1,nex,0);
}
else
{
ans+=dfs(x+1,mm[nex],0);
ans+=9*dfs(x+1,nex,0);
}
}
//printf("dp[%d][%d][%d]=%d\n",x,nex,flag,ans);
return dp[x][nex][flag]=ans;
}
int main()
{
int i,j,k,x,y;
mm[2]=0;
mm[0]=1;
mm[1]=8;
mm[8]=10;
memset(dp,-1,sizeof(dp));
scanf("%s",s+1);
n=strlen(s+1);
for(i=1;i<=n;i++)
{
a[i]=s[i]-'0';
}
dfs(1,2,1);
printf("%d\n",dp[1][2][1]);
return 0;
}
上一篇: 64位系统的KPCR结构
下一篇: 求1-100中有多少个9