首页 > 代码库 > HDU 5787 K-wolf Number(数位DP)
HDU 5787 K-wolf Number(数位DP)
【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5787
【题目大意】
求区间【L,R】内十进制数相邻k位之间不相同的数字的个数。
【题解】
很显然的数位dp,但是状态不知道该怎么转移,然后发现了递归数位DP这种神奇的姿势,每次记录前k位的数字,然后枚举下一位能用的数字,递归即可。
【代码】
#include <cstdio>#include <algorithm>#include <cstring> using namespace std;typedef long long ll;const int N=25,M=10005;int bit[N],pw[5],k;ll dp[N][M][2][2],l,r;ll DP(int d,int x,bool f,bool lim){ int c[5]; if(d==-1)return 1; ll &ret=dp[d][x][f][lim]; if(~ret)return ret; ret=0; int st=k-1,y=x,pos=0; for(int i=0;i<k;i++)c[i]=y%10,y/=10; if(!f){while(!c[st]&&st>=0)st--;} for(int i=st;i>=0;i--)pos|=1<<c[i]; int up=lim?bit[d]:9; for(int i=0;i<=up;i++){ if(pos>>i&1)continue; if(f)ret+=DP(d-1,(x-pw[k-1]*c[k-1])*10+i,f,lim&&i==up); else if(st==-1&&!i)ret+=DP(d-1,0,0,lim&&i==up); else ret+=DP(d-1,x*10+i,st==k-2,lim&&i==up); }return ret;}ll Cal(ll x){ if(!x)return 1;int cnt=0; while(x)bit[cnt++]=x%10,x/=10; memset(dp,-1,sizeof(dp)); return DP(cnt-1,0,0,1);}int main(){ for(int i=pw[0]=1;i<5;i++)pw[i]=pw[i-1]*10; while(~scanf("%lld%lld%d",&l,&r,&k)){ k--;printf("%lld\n",Cal(r)-Cal(l-1)); }return 0;}
HDU 5787 K-wolf Number(数位DP)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。