HZNUOJ B_M的忧虑 矩阵快速幂
程序员文章站
2022-03-10 22:44:26
B_M的忧虑DescriptionB_M学长喜欢减肥,为此他制定出了一个详细的减肥计划。因为这个计划过于详细,所以他甚至可以推算出在未来的某一天自己的体重。 体重的计算规律如下:要计算出自己某一天的体重,需要通过在此之前n天的体重来计算 设wx为第x天的体重,那么wx=∑ni=1(ai × wx−i) , 其中 ai 是给定的常数 现在给出B_M前n天的体重,询问他第x天的体重,题目保证x>nInput输入数据的第一行是两个正整数 n (1≤n≤100)和 x (...
B_M的忧虑
Description
B_M学长喜欢减肥,为此他制定出了一个详细的减肥计划。因为这个计划过于详细,所以他甚至可以推算出在未来的某一天自己的体重。
体重的计算规律如下:要计算出自己某一天的体重,需要通过在此之前n天的体重来计算
设wx为第x天的体重,那么wx=∑ni=1(ai × wx−i) , 其中 ai 是给定的常数
现在给出B_M前n天的体重,询问他第x天的体重,题目保证x>n
Input
输入数据的第一行是两个正整数 n (1≤n≤100)和 x (1≤x≤1018),第二行有 n 个非负整数,分别为 wn,wn−1,…w2,w1。第三行有 n 个非负整数,分别表示 a1,a2,…,an−1,an。(0≤ai,wi≤193)
Output
输出一个整数,表示对第 x 天的体重预测结果。结果需要对193取余,至于为什么我也不知道
Samples
input
2 3
5 9
3 3
output
42
**题解:**因为题目要求∑ni=1(ai × wx−i),我们想到用循环来暴力求解,但是因为数据范围给的很大,所以暴力求解是肯定行不通的,即乘积求和,所以我们可以(很自然)联想到转化为矩阵求和(这个很自然也不一定真的很自然),我们画几个矩阵可以找到一个推导公式,那么我们就可以用矩阵快速幂来求和
上图:
ac代码如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<map>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<set>
#include<cctype>
#include<string>
#include<stdexcept>
#include<fstream>
#include<sstream>
#define mem(a,b) memset(a,b,sizeof(a))
#define debug() puts("what the fuck!")
#define dedebug() puts("what the fuck!!!")
#define ll long long
#define ull unsigned long long
#define speed {ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); };
using namespace std;
const double PI = acos(-1.0);
const int maxn = 1e2 + 50;
const int N = 110;
const int INF = 0x3f3f3f3f;
const int inf = 0xfffffff;//比INF小,防止累加爆int
const double esp_0 = 1e-6;
const double gold = (1 + sqrt(5)) / 2;
const int mod = 193;
int gcd(int x, int y) {
return y ? gcd(y, x % y) : x;
}
ll n, x;
int a[maxn], w[maxn];
struct mat {
int r[maxn][maxn];
};
mat multi(mat x, mat y) {//矩阵乘法 方正*方正
mat step;
mem(step.r, 0);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
for (int k = 1; k <= n; k++) {
step.r[i][j] += x.r[i][k] * y.r[k][j];
step.r[i][j] %= mod;
}
}
}
return step;
}
mat multi2(mat x, mat y) {//题意描述的a矩阵*b矩阵
mat step;
mem(step.r, 0);
for (int i = 1; i <= n; i++) {
for (int k = 1; k <= n; k++) {
step.r[i][1] += x.r[i][k] * y.r[k][1];
step.r[i][1] %= mod;
}
}
return step;
}
ll mat_pow(ll time) {//矩阵快速幂
mat c, step;
mem(step.r, 0);
mem(c.r, 0);
for (ll i = 1; i <= n; i++) {
step.r[i][1] = w[n - i + 1];//将w数列读取到step方阵的第一列
}
//将a常数列读取到c方阵的第一行
for (ll i = 1; i <= n; i++) {
for (ll j = 1; j <= n; j++) {
//将c方阵的第二列至n列化为单位矩阵,保留前n天w,达到题目所要求的w前n天求和
if (i == 1)c.r[i][j] = a[j];
else {
if (j == i - 1)c.r[i][j] = 1;
}
}
}
while (time) {//矩阵快速幂
if (time & 1)step = multi2(c, step);//将time转化为2进制,如果为1,则进行题目乘法
c = multi(c, c);//不为1,c方阵快速幂算乘方
time = time >> 1;
}
return step.r[1][1];
}
//void init() {
// for (int i = 1; i <= n; ++i) {
// for (int j = 1; j <= n; ++j) {
// if (i - 1 == j)a.r[i][j] = 1;
// else a.r[i][j] = 0;
// }
// }
//}
int main() {
// init();
scanf("%lld %lld", &n, &x);
for (ll i = n; i >= 1; --i)scanf("%d", &w[i]);
for (ll i = 1; i <= n; ++i)scanf("%d", &a[i]);
ll res = mat_pow(x - n);
printf("%lld\n", res);
return 0;
}
本文地址:https://blog.csdn.net/qq_40924271/article/details/107879216
上一篇: form表单提交处理
下一篇: Python实现并查集