洛谷 P3413 SAC#1 - 萌數

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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章