洛谷 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 }
View Code
原文地址:https://www.cnblogs.com/i-caigou-TT/p/14371894.html