ACM-ICPC 2018 焦作赛区网络预赛 L - Poor God Water

//

#include <iostream>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <map>
#include <algorithm>
#include <queue>
#include <set>
#include <cmath>
#include <sstream>
#include <stack>
#include <fstream>
#include <ctime>
#pragma warning(disable:4996);
#define mem(sx,sy) memset(sx,sy,sizeof(sx))
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-8;
const double PI = acos(-1.0);
const ll llINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;

using namespace std;
const int msize = 9;
struct matrix {
	ll mat[msize][msize];

	matrix() {
		mem(mat, 0);
	}

	matrix(ll m[msize][msize]) {
		for (int i = 0; i < msize; i++) {
			for (int j = 0; j < msize; j++) {
				mat[i][j] = m[i][j];
			}
		}
	}

	friend matrix mul(matrix &a, matrix &b) {
		matrix c;
		for (int i = 0; i < msize; i++) {
			for (int j = 0; j < msize; j++) {
				for (int k = 0; k < msize; k++) {
					c.mat[i][k] += a.mat[i][j] * b.mat[j][k] % mod;
					c.mat[i][k] %= mod;
				}
			}
		}
		return c;
	}

	friend matrix qpow(matrix a, ll b) {
		matrix res;
		for (int i = 0; i < msize; i++) {
			res.mat[i][i] = 1;
		}
		while (b) {
			if (b & 1) {
				res = mul(a, res);
			}
			a = mul(a, a);
			b >>= 1;
		}
		return res;
	}
};

int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		ll n;
		scanf("%lld", &n);
		if (n == 1) {
			printf("3\n");
		}
		else {
			ll a[9][9] = {
				0,1,0,0,0,0,0,1,0,//0
				0,0,0,1,0,0,0,1,0,//1
				0,1,0,1,0,0,0,1,0,//2
				1,0,0,0,1,0,0,0,0,//3
				1,0,0,0,0,0,1,0,0,//4
				0,0,0,0,1,0,1,0,0,//5
				0,0,1,0,0,0,0,0,1,//6
				0,0,1,0,0,1,0,0,1,//7
				0,0,1,0,0,1,0,0,0 //8
			};
			matrix aa(a);
			matrix mans = qpow(aa, n - 2);
			ll fans = 0;
			for (int i = 0; i < 9; i++) {
				for (int j = 0; j < 9; j++) {
					fans += mans.mat[i][j];
					fans %= mod;
				}
			}
			printf("%lld\n", fans);
		}
	}
}
/*
0 mc 1mm(mmc) 7fm(fmc)
1 mm 3cm(cmm) 7fm(fmm)
2 mf 3cm(cmf) 1mm(mmf) 7fm(fmf)
3 cm 4cc(ccm) 0mc(mcm)
4 cc 0mc(mcc) 6fc(fcc)
5 cf 4cc(ccf) 6fc(fcf)
6 fc 8ff(ffc) 2mf(mfc)
7 fm 2mf(mfm) 5cf(cfm) 8ff(ffm)
8 ff 5cf(cff) 2mf(mff)
*/

矩阵快速幂板子

const int msize = 9;
struct matrix {
	ll mat[msize][msize];

	matrix() {
		mem(mat, 0);
	}

	matrix(ll m[msize][msize]) {
		for (int i = 0; i < msize; i++) {
			for (int j = 0; j < msize; j++) {
				mat[i][j] = m[i][j];
			}
		}
	}

	friend matrix mul(matrix &a, matrix &b) {
		matrix c;
		for (int i = 0; i < msize; i++) {
			for (int j = 0; j < msize; j++) {
				for (int k = 0; k < msize; k++) {
					c.mat[i][k] += a.mat[i][j] * b.mat[j][k] % mod;
					c.mat[i][k] %= mod;
				}
			}
		}
		return c;
	}

	friend matrix qpow(matrix a, ll b) {
		matrix res;
		for (int i = 0; i < msize; i++) {
			res.mat[i][i] = 1;
		}
		while (b) {
			if (b & 1) {
				res = mul(a, res);
			}
			a = mul(a, a);
			b >>= 1;
		}
		return res;
	}
};

过会再更新一个用ac自动机做的版本x

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值