https://www.luogu.org/problem/show?pid=3413
題解全是記憶化爆搜,嚇尿了都;
然後fop_zz秒了
百度果然搜不到題解,最後我在google 裏面找到了;
首先回文串嘛>2就好啦
所以我們只要判斷2情況
aa或者aba;
所以我們f[i][j][k]
表示第i位爲j
i-1位爲k的所有萌;
那麼顯然對於重複很難判斷;
所以我萌有2種方法,一是在開一維數組記錄是否出現;
另外的方法就是吧f[i][j][k]記錄的是當前狀態的非萌;
那我就用了第二種;
那麼這樣的話只要特判i=1的情況,f數組可以方便的求了;
那麼之後的話就是數位dp了;
#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const int N=1e3+5;
Ll f[N][10][10],mo=1e9+7,ans;
string l,r;
void dp(){
for(int i=2;i<=1000;i++)
for(int x=0;x<=9;x++)
for(int y=0;y<=9;y++)if(x!=y){
for(int z=0;z<=9;z++)
if(y!=z&&x!=z)
f[i][x][y]+=f[i-1][y][z];
if(i-1==1)f[i][x][y]++;
f[i][x][y]%=mo;
}
}
Ll out(string s){
int n=s.length(),X=-1,Y=-1;
Ll tot=0,ans=0;bool ok=1;
for(int i=0;i<n;i++)tot=(tot*10+s[i]-48)%mo;
for(int i=1;i<n;i++)
for(int x=1;x<=9;x++)
for(int y=0;y<=9;y++)
ans=(ans+f[i][x][y])%mo;
if(n>1)ans+=10;//10的含義是0~9這10個數字
for(int i=n;i>1;i--){
int v=s[n-i]-48;
for(int j=0;j<v;j++)if(i!=n||j!=0)
for(int k=0;k<=9;k++)
if(X!=j&&Y!=j&&j!=k&&k!=X)
ans=(ans+f[i][j][k])%mo;
if(v==X||v==Y){ok=0;break;}
Y=X;X=v;
}
if(ok)for(int j=0;j<=s[n-1]-48;j++)
if(j!=Y&&j!=X)ans=(ans+1)%mo;
return(tot+1-ans+mo)%mo;//1的含義就是0這個數字
}
int main()
{
dp();
cin>>l>>r;
ans=(out(r)-out(l)+mo)%mo;
for(int i=1;i<=l.length()-1;i++)
if(l[i]==l[i-1]||(i>1&&l[i]==l[i-2])){
ans=(ans+1)%mo;break;
}
printf("%lld",ans);
}