luoguP3413——高精度+數位dp

題目鏈接:https://www.luogu.com.cn/problem/P3413

 題目大意:

求[l,r]中滿足"存在長度至少爲2的迴文子串"的數的個數。

題解:

存在長度至少爲2的迴文子串意味着我們只需要考慮是否存在'aa'或者'aba'這種形式的子串就行了。

因此我們可以定義狀態爲dp[pos][pre1][pre2][flag]表示枚舉到pos位,pre1表示上一個數位,pre2表示上上一個數位,flag表示前面是否已經存在'aa'或者'aba'這種形式的迴文子串。

但是這裏我們需要把pre2初始化的值設爲-1,這樣有前導0時纔不會影響到非前導0的首位的下一位。

因爲數位最大爲1000,我們需要考慮用字符串存儲(其實更方便了),開始的l-1需要提前處理好。

代碼實現:

#pragma GCC optimize(2)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#define PI atan(1.0) * 4
#define E 2.718281828
#define rp(i, s, t) for (register int i = (s); i <= (t); i++)
#define RP(i, t, s) for (register int i = (t); i >= (s); i--)
#define ll long long
#define ull unsigned long long
#define mst(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define pii pair<int, int>
#define mp make_pair
#define pb push_back
#define debug printf("ac\n");
using namespace std;
inline int read()
{
    int a = 0, b = 1;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-')
            b = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9')
    {
        a = (a << 3) + (a << 1) + c - '0';
        c = getchar();
    }
    return a * b;
}
const ll mod = 1e9+7;
int a[1005],num;
ll dp[1005][10][10][2];
ll dfs(int pos,int pre1,int pre2,int flag,int lead,int limit){
    if(pos==-1) return flag;
    if(!lead&&!limit&&dp[pos][pre1][pre2][flag]!=-1&&pre2!=-1) return dp[pos][pre1][pre2][flag];
    int up=limit?a[pos]:9;
    ll ans=0;
    rp(i,0,up)
        ans=(ans+dfs(pos-1,i,lead?-1:pre1,flag||(!lead&&i==pre1)||(!lead&&i==pre2),lead&&i==0,limit&&i==a[pos]))%mod;
    if(!limit&&!lead&&pre2!=-1) return dp[pos][pre1][pre2][flag]=ans;
    return ans;
}
ll solve(string x){
    int len=x.size();
    num=0;
    int i=0;
    while(i<=len-1) a[num++]=x[len-i-1]-'0',i++;
    return dfs(num-1,0,-1,0,1,1);
}
int main(){
    string l,r;
    mst(dp,-1);
    cin>>l>>r;
    int len=l.size();
    if(l[len-1]-'0'>0) l[len-1]--;
    else{
        int index=len-1;
        while(l[index]=='0'&&index>0) l[index]='9',index--;
        l[index]--;
        string temp="";
        rp(i,0,len-1)
            if(l[i]!='0'){
                index=i;
                break;
            }
        rp(i,index,len-1) temp+=l[i];
        l=temp;
    }
    printf("%lld\n",((solve(r)-solve(l))+mod)%mod);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章