• BZOJ4037:[HAOI2015]数字串拆分——题解


    https://www.lydsy.com/JudgeOnline/problem.php?id=4037

    你有一个长度为n的数字串。定义f(S)为将S拆分成若干个1~m的数的和的方案数,比如m=2时,f(4)=5。

    你可以将这个数字串分割成若干个数字(允许前导0),将他们加起来,求f,并求和。比如g(123)=f(1+2+3)+f(1+23)+f(12+3)+f(123)。

    已知字符串和m后求答案对998244353(7*17*223+1,一个质数)取模后的值。

    神仙?(亦或是我从来没见过如此神奇的快速幂于是强行神仙?)

    参考:https://blog.csdn.net/H_Anonymity/article/details/78348610

    $f$数组一个矩乘快速幂求出,然而并没有卵用。

    我们令$f[i]$矩乘所需要的矩阵为$h[i]$。

    考虑使用dp求$g$,按位考虑,我们每次加上这位所能带来的贡献。

    ……或者说,乘上?因为$f(x1+x2)=$初始矩阵$*h[x1]*h[x2]$。

    于是令$dp[i]$表示前$i$位的求$g$矩阵,则我们有:

    $dp[i]=sum_{j=0}^{i-1}dp[j]*M_j$,其中$M_j=h[j+1$至$i$字符组成的数$]$。

    为了求出$M$,我们可以求$f[i][j]$表示$h[i*10^j]$这样我们就能很快捷的求出来了。

    听说这个就是神奇的十进制快速幂??

    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int p=998244353;
    const int L=505;
    char s[L];
    int n,m;
    struct matrix{
        ll g[6][6];
        matrix(){
            memset(g,0,sizeof(g));
        }
        inline void one(){
            for(int i=0;i<m;i++)g[i][i]=1;
        }
        matrix operator *(const matrix &b)const{
            matrix c;
            for(int i=0;i<m;i++)
                for(int j=0;j<m;j++)
                    for(int k=0;k<m;k++)
                           (c.g[i][j]+=g[i][k]*b.g[k][j]%p)%=p;
            return c;
        }
        matrix operator +(const matrix &b)const{
            matrix c;
            for(int i=0;i<m;i++)
                for(int j=0;j<m;j++)
                    c.g[i][j]=(g[i][j]+b.g[i][j])%p;
            return c;
        }
    }f[10][L],dp[L];
    matrix qpow(matrix x,ll y){
        matrix res;res.one();
        while(y){
            if(y&1)res=res*x;
            x=x*x;y>>=1;
        }
        return res;
    }
    void solve(){
        f[0][0].one();
        for(int i=0;i<m;i++)f[1][0].g[i][0]=1;
        for(int i=1;i<m;i++)f[1][0].g[i-1][i]=1;
        
        for(int i=1;i<=n;i++)f[0][i].one(),f[1][i]=qpow(f[1][i-1],10);
        for(int i=2;i<=9;i++)
            for(int j=0;j<=n;j++)f[i][j]=f[i-1][j]*f[1][j];
        dp[0].one();
        for(int i=1;i<=n;i++){
            matrix now=f[s[i]-'0'][0];
            for(int j=i-1;j>=0;j--){
                dp[i]=dp[i]+dp[j]*now;
                if(j)now=now*f[s[j]-'0'][i-j];
            }
        }
    }
    int main(){
        scanf("%s%d",s+1,&m);n=strlen(s+1);
        solve();
        printf("%d
    ",dp[n].g[0][0]);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

     +本文作者:luyouqi233。               +

     +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    Poj(1703),种类并查集
    Poj(2236),简单并查集
    Poj (3239),m皇后问题
    Poj(1521),哈夫曼编码
    NYOJ(680),摘枇杷,(暴力,或者二分搜索)
    NYOJ(42)欧拉图
    数集合有多少个TOJ(2469)
    HDU(1016),打素数环
    HDU(4394),数论上的BFS
    Poj(2225),三维BFS
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9221595.html
Copyright © 2020-2023  润新知