zoukankan      html  css  js  c++  java
  • 【Luogu】P3758可乐(矩阵优化DP)

      题目链接

      一开始想到这可能能用矩阵优化,但以为暴力就能卡过……T成二十分

      首先我们回顾一下我们的暴力转移方程

      用f[i][j][0/1]表示在i时刻,j点,1不爆炸,0已爆炸的方案数,那么f[i][j][0]=f[i-1][j][0]+f[i-1][j][1],f[i][j][1]=f[i-1][j][1]+f[i-1][k][1](其中k表示与j相邻的点)。

      然后我们看f[i][j][1]=f[i-1][j][1]+f[i-1][k][1]这个式子

      如果设定j和j相连,就化简为f[i][j][1]=f[i-1][k][1]

      然后就可以用矩阵乘法啦

      考虑到f[i][j][0]的求法,发现这是一个关于f[i-1][j][1]的和

      而我们发现f[i-1][j][1]是一串矩阵等比数列

      于是应用等比数列求和公式

      

    #include<algorithm>
    #include<cstdio>
    #include<cctype>
    #include<cstdlib>
    #include<cstring>
    #define mod 2017
    
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int n,m;
    
    struct Matrix{
        long long s[32][32];
        Matrix(){memset(s,0,sizeof(s));    }
        Matrix operator *(const Matrix &a){
            Matrix ans;
            for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j)
                    for(int k=1;k<=n;++k)
                        ans.s[i][j]=(ans.s[i][j]+(s[i][k]*a.s[k][j])%mod)%mod;
            return ans;
        }
        Matrix operator +(const Matrix &a){
            Matrix ans;
            for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j)
                    ans.s[i][j]=(s[i][j]+a.s[i][j])%mod;
            return ans;
        }
    };
    
    Matrix Pow(Matrix x,int p){
        Matrix ans;
        for(int i=1;i<=n;++i)    ans.s[i][i]=1;
        while(p){
            if(p&1)    ans=ans*x;
            x=x*x;
            p>>=1;
        }
        return ans;
    }
    
    Matrix Sum(Matrix x,int p){
        Matrix ans;
        if(!p)    return ans;
        for(int i=1;i<=n;++i)    ans.s[i][i]=1;
        ans=ans+Pow(x,p>>1);    ans=ans*Sum(x,p>>1);
        if(p&1)    ans=ans+Pow(x,p);
        return ans;
    }
    
    int q[300][300];
    Matrix Start;
    int ans;
    
    int main(){
        n=read(),m=read();
        for(int i=1;i<=m;++i){
            int from=read(),to=read();
            q[from][to]=q[to][from]=1;
        }
        for(int i=1;i<=n;++i)    q[i][i]=1;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)    Start.s[i][j]=q[i][j];
        int t=read();
        Matrix now;    now=Pow(Start,t);
        for(int i=1;i<=n;++i)    ans=(ans+now.s[i][1])%mod;
        Matrix sum;    sum=Sum(Start,t -1);
        for(int i=1;i<=n;++i)    sum.s[i][i]=(sum.s[i][i]+1)%mod;
        for(int i=1;i<=n;++i)    ans=(ans+sum.s[i][1])%mod;
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    阿里P8架构师谈:阿里双11秒杀系统如何设计?
    秒杀系统设计的知识点
    秒杀系统架构优化思路
    秒杀系统解决方案
    Entity Framework Code First (七)空间数据类型 Spatial Data Types
    Entity Framework Code First (六)存储过程
    Entity Framework Code First (五)Fluent API
    Entity Framework Code First (四)Fluent API
    Entity Framework Code First (三)Data Annotations
    Entity Framework Code First (二)Custom Conventions
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8052514.html
Copyright © 2011-2022 走看看