您的位置:首页 > 其它

fzu 1692(矩阵快速幂)

2015-05-30 19:00 357 查看
题意:有n个小朋友围一圈,初始每个人有ai个苹果,每轮过去,每个小朋友可以得到 ( L*A (i+n-1)%n+R*A (i+1)%n ) 个苹果,问m轮过后,每个小朋友有多少个苹果。

题解:普通的矩阵快速幂会超时,需要把矩阵乘法的三层循环变为两层,而且好像L和R位置应该是反的结果才正确。

#include <stdio.h>
#include <string.h>
const int N = 105;
struct Mat {
long long g

;
}ori, res, temp1;
long long n, m, l, r, MOD;

Mat multiply(Mat& x, Mat& y) {
Mat temp;
memset(temp.g, 0, sizeof(temp.g));
for (int k = 0; k < n; k++)
if (x.g[0][k]) {
for (int j = 0; j < n; j++)
if (y.g[k][j])
temp.g[0][j] = (temp.g[0][j] + x.g[0][k] * y.g[k][j]) % MOD;
}
for (int i = 1; i < n; i++) {
temp.g[i][0] = temp.g[i - 1][n - 1];
for (int j = 1; j < n; j++)
temp.g[i][j] = temp.g[i - 1][j - 1];
}
return temp;
}

void calc(long long m) {
for (int i = 0; i < n; i++)
temp1.g[i][i] = 1;
while (m) {
if (m & 1)
temp1 = multiply(temp1, res);
m >>= 1;
res = multiply(res, res);
}
}

int main() {
int t;
scanf("%d", &t);
while (t--) {
memset(ori.g, 0, sizeof(ori.g));
memset(res.g, 0, sizeof(res.g));
memset(temp1.g, 0, sizeof(temp1.g));
scanf("%lld%lld%lld%lld%lld", &n, &m, &l, &r, &MOD);
for (int i = 0; i < n; i++) {
scanf("%lld", &ori.g[0][i]);
ori.g[0][i] %= MOD;
res.g[(i + 1) % n][i] = l % MOD;
res.g[(i + n - 1) % n][i] = r % MOD;
res.g[i][i] = 1;
}
calc(m);
ori = multiply(ori, temp1);
printf("%lld", ori.g[0][0]);
for (int i = 1; i < n; i++)
printf(" %lld", ori.g[0][i]);
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: