1. 程式人生 > >L. Poor God Water(ACM-ICPC 2018 焦作賽區網絡預賽)

L. Poor God Water(ACM-ICPC 2018 焦作賽區網絡預賽)

方案 namespace bubuko oid mes icpc else -- eat

題意:有肉,魚,巧克力三種食物,有幾種禁忌,對於連續的三個食物,1.這三個食物不能都相同;2.若三種食物都有的情況,巧克力不能在中間;3.如果兩邊是巧克力,中間不能是肉或魚,求方案數

題解:聽其他隊說用杜教BM 就可以過 ???? orz orz

我發現自己不一樣啊!!!

我用的是矩陣快速冪,將meat , chocolate,fish 用 0 ,1 , 2 表示

對於 n 來說,我們只關註後兩位,因為 若 n - 1 的所有方案解決的話,我們在 n - 1 的方案添加0, 1,2 就行,然後根據禁忌 去除不可能的

我們根據次狀態 來更新現狀態,然後矩陣快速冪

  技術分享圖片

AC code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int N=9;
struct Matrix{
    ll matrix[N][N];
};

const int mod = 1e9 + 7;

void init(Matrix &res)
{
    memset(res.matrix,0,sizeof(res.matrix));
    for(int i=0;i<N;i++)
        res.matrix[i][i]
=1; } Matrix multiplicative(Matrix a,Matrix b) { Matrix res; memset(res.matrix,0,sizeof(res.matrix)); for(int i = 0 ; i < N ; i++){ for(int j = 0 ; j < N ; j++){ for(int k = 0 ; k < N ; k++){ res.matrix[i][j] += a.matrix[i][k]*b.matrix[k][j]; res.matrix[i][j]
%= mod; } } } return res; } Matrix pow(Matrix mx,ll m) { Matrix res,base=mx; init(res); while(m) { if(m&1) res=multiplicative(res,base); base=multiplicative(base,base); m>>=1; } return res; } int main() { int t; scanf("%d",&t); while(t--) { ll n,ant = 0; scanf("%lld",&n); if(n == 1) printf("3\n"); else if(n == 2) printf("9\n"); else { Matrix res,ans = { 0,0,0, 1,0,0, 1,0,0, 1,0,0, 0,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,0,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,0 }; res=pow(ans,n-2); for(int i = 0;i < N;i++) for(int j = 0;j < N;j++) ant = (ant + res.matrix[i][j]) % mod; printf("%lld\n",ant); } } return 0; }

L. Poor God Water(ACM-ICPC 2018 焦作賽區網絡預賽)