zoukankan      html  css  js  c++  java
  • 【noip2016十连测round3】T3 涂色游戏 【矩阵快速幂优化dp】

    涂色游戏

    这里写图片描述
    这里写图片描述
    题解:
    推一推公式。
    我们让f[i][j]表示第i列有j种颜色的方案总数,k表示i-1列用了多少种颜色,l表示第i列用了多少种没有在i-1列出现的颜色,G(i,j)表示i个格子涂j种颜色的方案总数。
    f[i][j]=Σ(f[i1][k]C(k,il)C(pk,l)G(n,j))。其中要满足k+l>=q
    G(i,j)怎么求?
    可以得到G(i,j)=jiΣ(g[i][k]c[j][k]),其中k=1..j1。这个式子代表先get到所有的涂法,再减去少于j种颜色的方案总数。
    但是我们发现列数为1e9,怎么办?
    太显然了吧!^ ^直接上矩阵快速幂优化。
    在最后orz orz %%%zjr大佬。老中医保佑!
    代码:

    #include<cstdio>
    #include<cstring>
    #pragma GCC optimize (3)
    typedef long long ll;
    const int N=105;
    const ll mod=998244353;
    int n,m,p,q;
    ll ans,c[N][N],g[N][N];
    ll fast_pow(ll a,int x){
        ll res=1;
        while(x){
            if(x&1){
                res*=a;
                res%=mod;
            }
            x>>=1;
            a*=a;
            a%=mod;
        }
        return res;
    }
    struct matrix{
        ll a[N][N];
        matrix(){
            memset(a,0,sizeof(a));
        }
        matrix operator * (const matrix &b) const{
            matrix c;
            for(int i=1;i<=p;i++){
                for(int j=1;j<=p;j++){
                    for(int k=1;k<=p;k++){
                        c.a[i][j]+=a[i][k]*b.a[k][j];
                        c.a[i][j]%=mod;
                    }
                }
            }
            return c;
        }
    }bg,x;
    int main(){
        scanf("%d%d%d%d",&n,&m,&p,&q);
        if(p<q){
            puts("0");
            return 0;
        }
        for(int i=0;i<=p;i++){
            c[i][0]=c[i][i]=1;
        }
        for(int i=1;i<=p;i++){
            for(int j=1;j<=i;j++){
                c[i][j]=c[i-1][j-1]+c[i-1][j];
                c[i][j]%=mod;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=i&&j<=p;j++){
                g[i][j]=fast_pow(j,i);
                for(int k=1;k<j;k++){
                    g[i][j]-=g[i][k]*c[j][k]%mod;
                    g[i][j]=(g[i][j]%mod+mod)%mod;
                }
            }
        }
        for(int i=1;i<=p&&i<=n;i++){
            for(int j=1;j<=p&&j<=n;j++){
                for(int k=0;k<=i;k++){
                    if(j+k<q){
                        continue;
                    }
                    x.a[j][i]+=c[j][i-k]*c[p-j][k]%mod*g[n][i]%mod;
                    x.a[j][i]%=mod;
                }
            }
        }
        for(int i=1;i<=p;i++){
            bg.a[1][i]=c[p][i]*g[n][i]%mod;
        }
        m--;
        while(m){
            if(m&1){
                bg=bg*x;
            }
            m>>=1;
            x=x*x;
        }
        for(int i=1;i<=p;i++){
            ans+=bg.a[1][i];
            ans%=mod;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Python 模块 itertools
    Python 字符串的encode与decode
    python 模块 hashlib(提供多个不同的加密算法)
    暴力尝试安卓gesture.key
    hdu 1300 Pearls(DP)
    hdu 1232 畅通工程(并查集)
    hdu 1856 More is better(并查集)
    hdu 1198 Farm Irrigation(并查集)
    hdu 3635 Dragon Balls(并查集)
    hdu 3038 How Many Answers Are Wrong(并查集)
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476880.html
Copyright © 2011-2022 走看看