• $[TJOI2017]$ 可乐 矩阵优化$dp$


    (Sol)

    (f_i)为到第(i)秒的方案数,显然(f_i=)在第(i)秒前爆炸的方案数+在第(i)秒爆炸的方案数+在第(i)秒停下的方案数+在第(i)秒走向下一个城市

    的方案数.注意到第四个转移和当前在哪个城市有关,所以要另记一维(j)表示当前位置.于是(f_{i,j}=)(i)秒前在(j)爆炸的方案数+第(i)秒在(j)爆炸的方案数+第(i)秒停在(j)的方案数+第(i)秒由别的城市走向(j)的方案数.记这四个量分别为(f1,f2,f3,f4).

    (f1_{i,j}=f1_{i-1,j}+f2_{i-1,j})

    (f2_{i,j}=f3_{i-1,j}+f4_{i-1,j})

    (f3_{i,j}=f3_{i-1,j}+f4_{i-1,j})

    (f4_{i,j}=f3_{i-1,k}+f4_{i-1,k}),其中,(k)(j)的相邻城市.

    这样瞎(dp)一下就可以获得(20pts)的好成绩(QAQ).

    其实上面的转移方程看起来就很矩阵优化的亚子,于是矩阵优化一下就好辣.

    (Code)

    #include<bits/stdc++.h>
    #define il inline
    #define Ri register int
    #define go(i,a,b) for(Ri i=a;i<=b;++i)
    #define yes(i,a,b) for(Ri i=a;i>=b;--i)
    #define e(i,u) for(Ri i=b[u];i;i=a[i].nt)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define db double
    #define inf 2147483647
    using namespace std;
    il int read()
    {
        Ri x=0,y=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
        return x*y;
    }
    const int mod=2017;
    int n,m,t,as;
    vector<int>to[31];
    struct mt
    {
        int a[121][121];bool ste;
        il void clear(){mem(a,0);ste=0;}
    }trs,cur;
    il void inc(Ri &x,Ri y){x+=y;if(x>=mod)x-=mod;}
    il mt operator * (mt x,mt y)
    {
        mt z;z.clear(),z.ste=x.ste;Ri h=x.ste?1:n*4;
        go(i,1,h)
    	go(j,1,n*4)
    	go(k,1,n*4)
    	inc(z.a[i][j],1ll*x.a[i][k]*y.a[k][j]%mod);
        return z;
    }
    il void init()
    {
        trs.clear();
        go(i,1,n)
        {
    	    Ri mi=(i-1)*4+1;
    	    trs.a[mi][mi]=trs.a[mi+1][mi]=1;
    	    trs.a[mi+2][mi+1]=trs.a[mi+3][mi+1]=1;
    	    trs.a[mi+2][mi+2]=trs.a[mi+3][mi+2]=1;
        	    go(j,0,(int)to[i].size()-1){Ri k=(to[i][j]-1)*4+3;trs.a[k][mi+3]=trs.a[k+1][mi+3]=1;}
        }
    }
    int main()
    {
        n=read(),m=read();
        go(i,1,m){Ri u=read(),v=read();to[u].push_back(v),to[v].push_back(u);}
        init();cur.clear();cur.a[1][3]=1,cur.ste=1;
        t=read();
        while(t){if(t&1)cur=cur*trs;trs=trs*trs;t>>=1;}
        go(i,1,n*4)inc(as,cur.a[1][i]);
        printf("%d
    ",as);
        return 0;
    }
    
    
  • 相关阅读:
    【leetcode】1630. Arithmetic Subarrays
    【leetcode】1629. Slowest Key
    【leetcode】1624. Largest Substring Between Two Equal Characters
    【leetcode】1620. Coordinate With Maximum Network Quality
    【leetcode】1619. Mean of Array After Removing Some Elements
    【leetcode】1609. Even Odd Tree
    【leetcode】1608. Special Array With X Elements Greater Than or Equal X
    【leetcode】1603. Design Parking System
    【leetcode】1598. Crawler Log Folder
    Java基础加强总结(三)——代理(Proxy)Java实现Ip代理池
  • 原文地址:https://www.cnblogs.com/forward777/p/11741808.html
Copyright © 2020-2023  润新知