试题 算法训练 奇异的虫群
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
在一个奇怪的星球上驻扎着两个虫群A和B,它们用奇怪的方式繁殖着,在t+1时刻A虫群的数量等于t时刻A虫群和B虫群数量之和,t+1时刻B虫群的数量等于t时刻A虫群的数量。由于星际空间的时间维度很广阔,所以t可能很大。OverMind 想知道在t时刻A虫群的数量对 p = 1,000,000,007.取余数的结果。当t=1时 A种群和B种群的数量均为1。
输入格式
测试数据包含一个整数t,代表繁殖的时间。
输出格式
输出一行,包含一个整数,表示对p取余数的结果
样例输入
样例一:
10
样例二:
65536
样例输出
样例一:
89
样例二:
462302286
数据规模与约定
对于50%的数据 t<=10^9
对于70%的数据 t<=10^15
对于100%的数据 t<=10^18
矩阵快速幂题目
代码
#include <stdio.h>
#define MOD 1000000007
typedef long long ll;
typedef struct ma {
ll m[2][2];
}mat;
mat E = {0}, B = {0};
mat sq(mat a, mat b) { //求矩阵a*b
mat c;
int i, j, k;
for(i = 0;i < 2; ++i) {
for(j = 0;j < 2; ++j) {
c.m[i][j] = 0;
for(k = 0;k < 2; ++k)
c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;
}
}
return c;
}
mat qpow(mat b, ll n) { // 求矩阵b的n次方
mat ans = E;
for(;n;n >>= 1, b = sq(b, b))
if(n&1) ans = sq(ans, b);
return ans;
}
int main() {
ll t;
scanf("%lld", &t);
if(t < 4) {
printf("%lld", t);
return 0;
}
int i;
for(i = 0;i < 2; ++i)
E.m[i][i] = 1;
B.m[0][0] = B.m[0][1] = B.m[1][0]= 1;
mat ans = qpow(B, t - 2); // 求B的t-2次方, 矩阵A=[a2,a1]=[2,1]
printf("%lld", (2 * ans.m[0][0] + ans.m[1][0]) % MOD); //对应相乘
return 0;
}