zoukankan      html  css  js  c++  java
  • NOI2020D1T1美食家

    传送门:QAQQAQ

    完了完了NOI签到题全班打不出来,真就全部成为时代的眼泪了。。。

    首先$O(mT)$的$dp$显然,然后因为$T$很大$w$很小矩阵快速幂显然,但是有$k=200$卡不过去。

    然后因为行向量乘上转移矩阵是$O(n^{2})$的,所以我们枚举的$k$时只用行向量乘上转移矩阵,转移矩阵的自乘放在外面倍增预处理,这样复杂度是$O(n^{2}*k*log(V)+(n^{3}*log(V)))$,开了O2非常稳

    所以最近两道几乎正解的矩乘都没打出来。。一道倍增预处理转移矩阵优化,一道先DFT转点值再快速幂而不是每次快速幂用FFT优化来将复杂度。。

    菜是原罪。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    const ll inf=(ll)1e15;
    #define mk make_pair
    void checkmin(ll &x,ll y){if(x>y) x=y;}
    void checkmax(ll &x,ll y){if(x<y) x=y;}
    const int N=2010;
    vector<pii> v[N],G[N];
    int t[N],X[N],Y[N],c[N];
    int n,m,T,k;
    struct Edge
    {
        int from,to,cost;
    }E[N];
    
    
    void init()
    {
        scanf("%d%d%d%d",&n,&m,&T,&k);
        for(int i=1;i<=n;i++) scanf("%d",&c[i]);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&E[i].from,&E[i].to,&E[i].cost);
            v[E[i].from].push_back(mk(E[i].to,E[i].cost));
            G[E[i].to].push_back(mk(E[i].from,E[i].cost));
        }
        for(int i=1;i<=k;i++) scanf("%d%d%d",&t[i],&X[i],&Y[i]);
    }
    
    namespace solver1{
        ll dp[52600][55]; int a[52600][55];
        void init()
        {
            memset(a,0,sizeof(a));
            for(int i=1;i<=k;i++) a[t[i]][X[i]]=Y[i];
        }
        void main()
        {
            init();
            for(int i=0;i<=T;i++)
                for(int j=1;j<=n;j++) dp[i][j]=-inf;
            dp[0][1]=c[1];
            for(int i=1;i<=T;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    for(int p=0;p<(int)G[j].size();p++)
                    {
                        int to=G[j][p].first,w=G[j][p].second;
                        if(i<w) continue;
                        checkmax(dp[i][j],dp[i-w][to]+c[j]);
                    }
                }
                for(int j=1;j<=n;j++) dp[i][j]+=a[i][j];
            }
            if(dp[T][1]<=0) puts("-1");
            else printf("%lld
    ",dp[T][1]);
        }
    }
    
    struct matrix{
        ll a[255][255];
        int n,m;
        matrix(){}
        matrix(int n,int m):n(n),m(m){
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++) a[i][j]=-inf;
        }
    };
    
    matrix operator * (matrix A,matrix B)
    {
        matrix C(A.n,B.m);
        for(int i=1;i<=C.n;i++)
        {
            for(int k=1;k<=A.m;k++)
            {
                if(A.a[i][k]==-inf) continue;
                for(int j=1;j<=C.m;j++) 
                    checkmax(C.a[i][j],A.a[i][k]+B.a[k][j]);
            }
        }
        return C;
    }
    
    struct LI{
        int t,x,y;
        LI(){}
        LI(int t,int x,int y):t(t),x(x),y(y){}
        bool operator < (const LI &rhs) const{
            return t<rhs.t;
        }
    }limit[N];
    
    matrix Base[31];
    void Qpow(matrix &A,int y)
    {
        matrix ret(A.n,A.m);
        for(int i=1;i<=A.n;i++) ret.a[i][i]=0;
        for(int i=30;i>=0;i--)
        {
            if((1<<i)<=y) y-=(1<<i),A=A*Base[i];
        }
    }
    
    namespace solver2{
        ll dp1[7][55]; int a[7][55];
        void init()
        {
            memset(a,0,sizeof(a));
            for(int i=1;i<=k;i++) 
                if(t[i]<=5) a[t[i]][X[i]]=Y[i];
        }
        void build()
        {
            init();
            for(int i=0;i<=5;i++)
                for(int j=1;j<=n;j++) dp1[i][j]=-inf;
            dp1[0][1]=c[1];
            for(int i=1;i<=5;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    int u=E[j].from,to=E[j].to,w=E[j].cost;
                    if(i<E[j].cost) continue;
                    if(dp1[i-w][u]==-inf) continue;
                    checkmax(dp1[i][to],dp1[i-w][u]+c[to]);
                }
                for(int j=1;j<=n;j++) dp1[i][j]+=a[i][j];
            }
        }
        void main()
        {
            build();
            int TMP=0;
            for(int i=1;i<=k;i++)
            {
                if(t[i]<=5) i--,k--,TMP++;
                limit[i]=LI(t[i+TMP],X[i+TMP],Y[i+TMP]);
            }
            sort(limit+1,limit+k+1);
            matrix A(1,n*5);
            for(int i=1;i<=5;i++)
            {
                for(int j=1;j<=n;j++) A.a[1][(i-1)*n+j]=dp1[i][j]; 
            }
            //print(A);
            for(int i=0;i<=30;i++) 
            {
                Base[i].m=Base[i].n=5*n; 
                for(int j=1;j<=5*n;j++)
                {
                    for(int t=1;t<=5*n;t++)
                    {
                        Base[i].a[j][t]=-inf;
                    }
                }
            }
            for(int j=1;j<=n*4;j++) Base[0].a[j+n][j]=0;
            for(int i=1;i<=m;i++)
            {
                int u=E[i].from,to=E[i].to,w=E[i].cost;
                int from=(5-w)*n+u; to=4*n+to;
                Base[0].a[from][to]=c[E[i].to];
            }
            //print(Base);
            for(int i=1;i<=30;i++) Base[i]=Base[i-1]*Base[i-1];
    
            T-=5;
            for(int i=1;i<=k;i++) limit[i].t-=5;
            int now=0;
            for(int i=1;i<=k;i++)
            {
                int pos=limit[i].t;
                Qpow(A,pos-now);
                now=pos;
                if(A.a[1][4*n+limit[i].x]==-inf) continue;
                else A.a[1][4*n+limit[i].x]+=limit[i].y;
            }
    
            Qpow(A,T-now);
            if(A.a[1][4*n+1]<=0) puts("-1");
            else printf("%lld
    ",A.a[1][4*n+1]);
        }
    }
    
    namespace solver3{
        int dis[N],vis[N];
        ll tot=0;
        void dfs(int u){
            if(vis[u]) return;
            vis[u]=1;
            for(int i=0;i<(int)v[u].size();i++)
            {
                int to=v[u][i].first,w=v[u][i].second;
                dis[to]=dis[u]+w;
                dfs(to);
            }
        }
        void main()
        {
            memset(vis,0,sizeof(vis)); dis[1]=0;
            dfs(1);
            if(T%dis[1]!=0) 
            {
                puts("-1");
                return;
            }
            ll ans=c[1];
            for(int i=1;i<=k;i++)
            {
                if((t[i]-dis[X[i]])%dis[1]==0) ans+=Y[i];
            }
            for(int i=1;i<=n;i++) tot+=c[i];
            ans+=T/dis[1]*tot;
            printf("%lld
    ",ans);
        }
    }
    
    bool iscircle()
    {
        if(n!=m) return 0;
        for(int i=1;i<=m;i++)
        {
            if(E[i].to!=E[i].from%n+1) return 0;
        }    
        return 1;
    }
    
    void solve()
    {
        if(T<=52600) 
        {
            solver1::main();
            return;
        }
        if(iscircle())
        {
            solver3::main();
            return;
        }
        solver2::main();
        return;
    }
    
    int main()
    {
        //freopen("delicacy.in","r",stdin);
        //freopen("delicacy.out","w",stdout);
        init();
        solve();
        fclose(stdin); fclose(stdout);
        return 0;
    }
    View Code
  • 相关阅读:
    Docker实践之03-Dockerfile指令详解
    Docker实践之02-使用镜像及定制
    通过Hack方式实现SDC中Stage配置联动刷新
    多级部门查询性能问题解决方案
    Docker实践之01-入门介绍
    从阿里腾讯2朵云产品中学到的用户体验
    HttpClient在多线程环境下踩坑总结
    一次对JDK进行"减肥"的记录
    北京西站如何进站接人
    多实例集群部署下的图片上传和访问
  • 原文地址:https://www.cnblogs.com/Forever-666/p/13526409.html
Copyright © 2011-2022 走看看