根据题目,要求什么设什么。
因为题目要求的是m以后第n个符合的数,在数位dp中,求出数的答案个数,总是单调递增的,由此可以分析出需要二分答案。
对于dp如何设定状态,由于题目要求一个“明七”,一个“暗七”,那么明七很明显就是有没有某个数位出现7,用一个变量have来表示,“暗七”就在最后算完的时候,看看能不能被7取模,然后每步加的时候都取模7,方便使用f数组来进行记忆化。
#include <bits/stdc++.h> using namespace std; #define int long long int f[20][10][2]; int a[20]; int dp(int pos,int mod,bool have,bool flag) { if(pos==0) return mod%7==0||have; if(flag&&f[pos][mod][have]!=-1) return f[pos][mod][have]; int x=flag?9:a[pos]; int ans=0; for(int i=0;i<=x;i++) { ans+=dp(pos-1,(mod*10+i)%7,have||i==7,flag||i<x); } if(flag) f[pos][mod][have]=ans; return ans; } int cul(int x) { int pos=0; while(x) { a[++pos]=x%10; x/=10; } return dp(pos,0,false,false); } signed main() { memset(f,-1,sizeof(f)); int m,n; scanf("%lld%lld",&m,&n); int l=m+1,r=m+7*(n+1); int mid; int p=cul(m); while(l<r) { mid=(l+r)>>1; if(cul(mid)-p>=n) r=mid; else l=mid+1; } printf("%lld\n",l); }