2020/11/03 模擬賽 偶數


Description

牛牛喜歡偶數,他定義一種新的“偶數”為:(在十進制下,去掉前導零)數字的位 數為偶數,且數字前一半和后一半完全一致。比如 121121、12341234 是“偶 數”,而 111、121212 不是“偶數”。 對於一個“偶數”,牛牛可以在這個“偶數”后繼續添加數字,使得它成為新的“偶 數”。比如, 121121 可以在后面添加數字,使之變成 1211212112 成為新的 “偶數”。牛牛總是想添加最少的數字獲得新的“偶數”。可以證明添加的方式是唯 一的。 對於任何一個“偶數”,牛牛都可以通過上述的方式產生新的“偶數”,這個新的 “偶數”繼續產生下一個新的“偶數”,直到這個“偶數”的位數超過任意給定的正整 數 $n$ 為止。之后,牛牛會多次詢問你,這個最終的“偶數”的第 $l$ 位到第 $r$ 位$1 \leq l \leq r \leq n$組成的整數 模 $998244353$ 后是多少。

Solution

題中要求的偶數是前一半與后一半完全相同的數,並可以復制給出的原數使其不斷擴展成一個新的偶數,最后求超過給定位數的偶數的指定數位區間所顯示的數

對於一個偶數,新擴展出的偶數一定是它加上它的最小周期

不斷如此處理,直至長度超過給定長度

維護一些值

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int T,nxt[100005],q,lim;
long long fs[100005],n,m,len[100],f[100],ten[100];
const long long mod=998244353;
char s[100005];
inline long long read()
{
    long long w=0,f=1;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    return w*f;
}
void getNext()
{
    int i=0,j=nxt[0]=-1;
    while(i<n)
    {
        while(j!=-1&&s[i]!=s[j]) j=nxt[j];
        nxt[++i]=++j;
    }
}
long long ksm(long long a,long long p)
{
    long long ret=1;
    while(p)
    {
        if(p&1) (ret*=a)%=mod;
        (a*=a)%=mod,p>>=1;
    }
    return ret;
}
long long sol(long long m)
{
    long long sum=0,ret=0;
    for(int i=lim;i>=0;i--)
    {
        if(sum+len[i]<=m)
        {
            ret=(ret*ten[i]%mod+f[i])%mod;
            sum+=len[i];
        }
    }
    ret=(ret*ksm(10,m-sum)%mod+fs[m-sum])%mod;
    return ret;
}
int main()
{
    T=read();
    for(;T;T--)
    {
        scanf("%s",s);
        n=strlen(s)/2;
        getNext();
        for(int i=1;i<=n;i++) fs[i]=(fs[i-1]*10+s[i-1]-'0')%mod;
        m=read(),q=read();
        len[0]=n-nxt[n],f[0]=fs[len[0]];
        len[1]=n,f[1]=fs[n];
        for(int i=2;i<100;i++)
        {
            len[i]=len[i-1]+len[i-2];
            f[i]=(f[i-1]*ksm(10,len[i-2])%mod+f[i-2])%mod;
            if(len[i]>=m)
            {
                lim=i;break;
            }
        }
        for(int i=0;i<=lim;i++) ten[i]=ksm(10,len[i]);
        for(int i=1;i<=q;i++)
        {
            long long l=read(),r=read();
            printf("%lld\n",(sol(r)-sol(l-1)*ksm(10,r-l+1)%mod+mod)%mod);
        }
    }
    return 0;
}
偶數

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM