洛谷 P3413 SAC#1 - 萌数
这道题用了正难则反的思想,毕竟正面求回文很麻烦,不知道长度也不知道位置。
但是可以求不构成回文的数然后做补集。
dp[i][j][k]表示前i位前两个数字是j,前一个数字是k,不构成回文的数量。
注意消除前导零的影响。
下附代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const ll MOD=1e9+7; 5 ll dp[1005][10][10],dim[1005]; 6 ll dfs(int x,int st,int pre,int jb,int fz){ 7 if (!x){ 8 return 1; 9 } 10 if (!jb && dp[x][st][pre]!=-1 && !fz && pre!=-1 && st!=-1) return dp[x][st][pre]; 11 ll ret=0; 12 int maxn=9; 13 if (jb) maxn=dim[x]; 14 for (int i=0; i<=maxn; i++){ 15 if (fz==1){ 16 if (i==0) ret=(ret+dfs(x-1,-1,-1,(jb==1 && i==maxn),1))%MOD; 17 else ret=(ret+dfs(x-1,i,-1,(jb==1 && maxn==i),0))%MOD; 18 } 19 else { 20 if (i!=st && i!=pre) ret=(ret+dfs(x-1,i,st,(jb==1 && maxn==i),0))%MOD; 21 } 22 } 23 if (!jb && !fz && pre!=-1 && st!=-1) return dp[x][st][pre]=ret; 24 return ret; 25 } 26 int main(){ 27 memset(dp,-1,sizeof(dp)); 28 string a,b; 29 cin>>a>>b; 30 for (int i=0; i<a.length(); i++){ 31 dim[a.length()-i]=a[i]-'0'; 32 } 33 dim[1]-=1; 34 int j=1; 35 while (dim[j]<0){ 36 dim[j]+=10; 37 dim[j+1]-=1; 38 j++; 39 } 40 int len=a.length(); 41 while (dim[len]==0 && len>1) len--; 42 ll l=dfs(len,-1,-1,1,1); 43 for (int i=0; i<b.length(); i++){ 44 dim[b.length()-i]=b[i]-'0'; 45 } 46 ll r=dfs(b.length(),-1,-1,1,1); 47 ll numl=0,numr=0; 48 for (int i=0; i<a.length(); i++){ 49 numl=(numl*10+a[i]-'0'+MOD)%MOD; 50 } 51 numl=(numl-1+MOD)%MOD; 52 for (int i=0; i<b.length(); i++){ 53 numr=(numr*10+b[i]-'0')%MOD; 54 } 55 printf("%lld",((numr-numl+MOD)%MOD-(r-l+MOD)%MOD+MOD)%MOD); 56 }