@lychee123
2017-09-11T06:31:07.000000Z
字数 1091
阅读 1176
数论
题面链接:HDU 6185:Covering
题意
求用 的格子去填满 的矩阵一共有多少种方法
分析
通过模板找出他们之间的关系式,然后对于该模板进行小细节的改动就OK(我这写的啥阿)
#include<bits/stdc++.h>using namespace std;const int mod = 1000000007;typedef long long LL;const int M = 4;const int base[M][M] ={{ 1, 5, 1, -1 },{ 1, 0, 0, 0 },{ 0, 1, 0, 0 },{ 0, 0, 1, 0 },}; //需要进行k次方的矩阵,通过关系式推出的矩阵方程const int source[M][M] ={{ 36, 0, 0, 0 },{ 11, 0, 0, 0 },{ 5, 0, 0, 0 },{ 1, 0, 0, 0 },}; //用于存答案的矩阵struct Mat //矩阵{int a[M][M]; //矩阵数据Mat() //矩阵默认构造函数,初始化数据全0{memset(a, 0, sizeof(a));}Mat(const int g[M][M]) //有参构造函数,拷贝给定数组的元素作为矩阵数据{memcpy(a, g, sizeof(a));}void E() //构造单位矩阵,这个如果要用,应该位于默认构造之后{for (int i = 0; i < M; i++)a[i][i] = 1;}Mat operator * (const Mat &b) const //重载矩阵乘法{Mat ret;for (int i = 0; i < M; i++)//此处要改M代表与M项相关for (int k = 0; k < M; k++){if (a[i][k] == 0)continue;for (int j = 0; j < M; j++){ret.a[i][j] += (LL)a[i][k] * b.a[k][j] % mod;if (ret.a[i][j] >= mod)ret.a[i][j] -= mod;if (ret.a[i][j] < 0)ret.a[i][j] += mod; //矩阵中用负数,取模要注意}}return ret;}};Mat bin(const Mat &a, LL k){Mat ret;ret.E();Mat res;res = a;while (k){if (k & 1)ret = ret * res;res = res * res;k >>= 1;}return ret;}int main(){LL n;while (~scanf("%lld", &n)){Mat ret = bin(Mat(base), n - 1);ret = ret * Mat(source);printf("%d\n", ret.a[3][0]);}return 0;}