HZNUOJ B_M's worry matrix fast power

B_M's worries

Description
B_M senior likes to lose weight, so he worked out a detailed weight loss plan. Because this plan is too detailed, he can even calculate his weight in the future.

    体重的计算规律如下:要计算出自己某一天的体重,需要通过在此之前n天的体重来计算

    设wx为第x天的体重,那么wx=∑ni=1(ai × wx−i) , 其中 ai 是给定的常数

    现在给出B_M前n天的体重,询问他第x天的体重,题目保证x>n


The first line of Input data is two positive integers n (1≤n≤100) and x (1≤x≤1018), and the second line has n non-negative integers, which are wn, wn−1,...w2 ,w1. The third line has n non-negative integers, which represent a1, a2,...,an−1,an respectively. (0≤ai,wi≤193)

Output
outputs an integer that represents the weight prediction result on day x. As a result, I need to take the remainder of 193. As for why I don’t know why

Samples
input
2 3
5 9
3 3
output
42

**Problem solution: **Because the problem requires ∑ni=1(ai × wx−i), we thought of using a loop to solve it violently, but because the data range is large, the violent solution is definitely not feasible, that is, product seeking Sum, so we can (naturally) think of transforming into matrix summation (this is natural and not necessarily really natural), we can draw a few matrices to find a derivation formula, then we can use the matrix fast power to find And
the picture above: The
emmm, is it a derivation process?
ac code is as follows :

#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;
}

Guess you like

Origin blog.csdn.net/qq_40924271/article/details/107879216