题意:求[a,b]中,偶数位的数字都是d,其余为数字都不是d,且能被m整除的数的个数(这里的偶数位是的是从高位往低位数的偶数位)。a,b<10^2000,m≤2000,0≤d≤9 a,b<10^2000,m≤2000,0≤d≤9
题解:用f[i][j]表示有i+1位,第i位是d,且%m=j的数的个数。(这个状态可能有点奇怪,不过比较便于转移)然后转移方式还是惯用的方法,判一下如果原数的偶数位不是d或者奇数位是d则停止计算即可。
自主AC开心

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int maxn=2010; const ll mod=1e9+7; ll dp[maxn][maxn]; char a[maxn], b[maxn]; int wei[maxn], m, d; ll dfs(int pos, ll sum, bool limit, int len){ if(pos==-1) return sum==0; if(!limit && dp[pos][sum]!=-1) return dp[pos][sum]; ll ans=0; int up= limit ? wei[pos] : 9; for(int i=0; i<=up; i++) { if((len-pos)%2==0 && i!=d) continue; if((len-pos)%2==1 && i==d) continue; ans=(ans%mod+dfs(pos-1, (sum*10+i)%m, limit&&(i==wei[pos]), len)%mod)%mod; } return limit ? ans : dp[pos][sum]=ans; } ll solve(char *s){ int len=strlen(s); for(int i=0; i<len; i++) { wei[i]=s[len-i-1]-'0'; } return dfs(len-1, 0, true, len); } bool check(){ int len=strlen(a); ll s=0; for(int i=0; i<len; i++) { s=(s*10+a[i]-'0')%m; if((i+1)%2==0 && a[i]-'0'!=d || (i+1)%2==1 && a[i]-'0'==d) return false; } if(!s) return true; else return false; } int main(){ memset(dp, -1, sizeof(dp)); scanf("%d%d", &m, &d); scanf("%s%s", a, b); ll ans=solve(b)-solve(a); if(check()){//判断a是否合格 ans++; } ans=(ans+mod)%mod; printf("%lld ", ans); return 0; }