ACM-ICPC 2018 焦作赛区网络预赛 Poor God Water 矩阵快速幂
Posted lhclqslove
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM-ICPC 2018 焦作赛区网络预赛 Poor God Water 矩阵快速幂相关的知识,希望对你有一定的参考价值。
题目链接:Poor God Water
题意:有N个小时,有三种食物(用1 ,2 ,3代替好了),每个小时要吃一种食物,要求任意连续三个小时不能出现111,222,333,132,231,313,323
的方案数
题解:dp[i][j]表示最后两种食物分别为i,j的方案数,转移就是在增加一种食物,可以根据要求推出下面的递推矩阵.
然后就可以用矩阵快速幂了。然后我还加了个离线的小优化(50ms)。
#include<bits/stdc++.h> #define ll long long using namespace std; const int mod=1e9+7; int n; int an[1005]; struct que { ll x; int id; bool operator<(const que b)const { return x<b.x; } }q[1005]; struct mat { int n, m; ll a[15][15]; mat() {} void init(int _n, int _m) { n = _n; m = _m; for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) a[i][j] = 0; } } void one() { init(2,2);a[0][0]=1;a[1][1]=1; } mat operator + (const mat &B)const { mat C; C.init(n,m); for(int i=0; i<n; i++) for(int j=0; j<m; j++) C.a[i][j]=(a[i][j]+B.a[i][j])%mod; return C; } mat operator*(const mat &P)const { mat ret; ret.init(n,m); for(int i = 0; i < n; i++) { for(int k = 0; k < m; k++) { if(a[i][k]) { for(int j = 0; j < P.m; j++) { ret.a[i][j] = ((ll)a[i][k] * P.a[k][j] + ret.a[i][j]) % mod; } } } } return ret; } mat operator^(const ll &P)const { ll num = P; mat ret, tmp = *this; ret.init(n,m); for(int i = 0; i < n; i++) ret.a[i][i] = 1; while(num) { if(num & 1) ret = ret * tmp; tmp = tmp * tmp; num >>= 1; } return ret; } void view() { for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { printf("%lld ",a[i][j]); }printf(" "); } } }ap,ac,ad; void init() { ac.init(9,9); ac.a[3][0]=1;ac.a[6][0]=1; ac.a[0][1]=1;ac.a[3][1]=1;ac.a[6][1]=1; ac.a[0][2]=1;ac.a[3][2]=1; ac.a[1][3]=1;ac.a[4][3]=1;ac.a[7][3]=1; ac.a[1][4]=1;ac.a[7][4]=1; ac.a[1][5]=1;ac.a[4][5]=1; ac.a[2][6]=1;ac.a[8][6]=1; ac.a[5][7]=1;ac.a[8][7]=1; ac.a[2][8]=1;ac.a[5][8]=1; ad.init(9,9); for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { ad.a[i][j]=ac.a[i][j]; } } } int main() { int T; scanf("%d",&T); init(); for(int i=1;i<=T;i++) { scanf("%lld",&q[i].x); q[i].id=i; } sort(q+1,q+T+1); ll p=3; for(int i=1;i<=T;i++) { if(q[i].x==1) { an[q[i].id]=3; } else if(q[i].x==2) { an[q[i].id]=9; } else { ad=ad*(ac^(q[i].x-p)); p=q[i].x; ll ans=0; ap.init(1,9); for(int i=0;i<9;i++) { ap.a[0][i]=1; } ap=ap*ad; for(int i=0;i<9;i++) { ans+=ap.a[0][i]; ans%=mod; } an[q[i].id]=ans; } } for(int i=1;i<=T;i++) { printf("%d ",an[i]); } }
以上是关于ACM-ICPC 2018 焦作赛区网络预赛 Poor God Water 矩阵快速幂的主要内容,如果未能解决你的问题,请参考以下文章
ACM-ICPC 2018 焦作赛区网络预赛 B题 Mathematical Curse
ACM-ICPC 2018 焦作赛区网络预赛 Solution
ACM-ICPC 2018 焦作赛区网络预赛 G题 Give Candies