zoukankan      html  css  js  c++  java
  • BZOJ 4037 [HAOI2015]数字串拆分 ——动态规划

    拆分的情况下,发现f数组本身并不是很好递推。

    因为f(123)=f(123)/f(12+3)/f(1+2+3)。

    然后考虑f可以怎么表示f(n)=a0*M^n M为转移矩阵。

    然后发现 f(x+y)=a0*M(x+y), 所以只需要对M矩阵进行DP即可。

    这样子每一个位置就可以表示为若干转移矩阵的和,然后就可以利用矩阵的相乘进行递推。

    最后直接用原向量乘上转移矩阵即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
     
    #define ll long long
    #define F(i,j,k) for (ll i=j;i<=k;++i)
    #define D(i,j,k) for (ll i=j;i>=k;--i)
    const ll md=998244353;
     
    ll m,l;char s[505];
     
    struct matrix{
        ll x[6][6];
        void init(){memset(x,0,sizeof x);}
        void build1(){
            init();
            x[1][1]=1;
        }
        void build2(){
            init();
            F(i,1,m) x[i][1]=1;
            F(i,1,m-1) x[i][i+1]=1;
        }
        void build3(){
            init();
            F(i,1,m) x[i][i]=1;
        }
        matrix operator * (matrix b) {
            matrix ret;
            ret.init();
            F(i,1,m) F(j,1,m)
            {
                F(k,1,m)
                ret.x[i][j]=ret.x[i][j]+x[i][k]*b.x[k][j];
                ret.x[i][j]%=md;
            }
            return ret;
        }
        matrix operator + (matrix b) {
            matrix ret;
            ret.init();
            F(i,1,m) F(j,1,m)
                ret.x[i][j]=((ll)x[i][j]+(ll)b.x[i][j])%md;
            return ret;
        }
    }dp[505],one,c[11][501],turn,now,ans;
     
    int main()
    {
        scanf("%s",s+1);l=strlen(s+1);
        scanf("%lld",&m);
        F(i,0,l) dp[i].init();
        one.build1();
        turn.build2();
        c[0][0].build3();
        F(i,1,10) c[i][0]=c[i-1][0]*turn;
        F(i,1,l-1)
        {
            c[0][i]=c[0][i-1];
            c[1][i]=c[10][i-1];
            F(j,2,10)
            {
                c[j][i]=c[j-1][i]*c[10][i-1];
            }
        }
        dp[0].build3();
        F(i,1,l)
        {
            now.build3();
            D(j,i,1)
            {
                now=now*c[s[j]-'0'][i-j];
                dp[i]=dp[i]+dp[j-1]*now;
            }
        }
        ans=dp[l]*one;
        printf("%lld
    ",ans.x[1][1]);
    }
    

      

  • 相关阅读:
    python 笔记8
    python笔记6
    python笔记5
    python笔记4
    python笔记3
    python课程2
    cobbler 坑爹指南
    hadoop filesystem 删除文件 复制文件 重命名文件
    hadoop 文件 复制 移动 FileUtil.copy
    soinn
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6582010.html
Copyright © 2011-2022 走看看