Matriz de preocupaciones de HZNUOJ B_M, potencia rápida

Las preocupaciones de B_M

Descripción A
B_M senior le gusta perder peso, por lo que elaboró ​​un plan de pérdida de peso detallado. Debido a que este plan es demasiado detallado, incluso puede calcular su peso en el futuro.

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

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

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


La primera línea de datos de entrada son dos enteros positivos n (1≤n≤100) y x (1≤x≤1018), y la segunda línea tiene n enteros no negativos, que son wn, wn − 1, ... w2, w1. La tercera línea tiene n números enteros no negativos, que representan a1, a2, ..., an − 1, an respectivamente. (0≤ai, wi≤193)

La salida
genera un número entero que representa el resultado de la predicción de peso el día x. Como resultado, necesito tomar el resto de 193. En cuanto a por qué no sé por qué

Muestras
entrada
2 3
5 9
3 3
salida
42

** Solución del problema: ** Debido a que el problema requiere ∑ni = 1 (ai × wx − i), pensamos en usar un bucle para resolverlo violentamente, pero debido a que el rango de datos es grande, la solución violenta definitivamente no es factible, es decir, suma de búsqueda de productos, por lo que podemos (naturalmente) pensar en transformarnos en una suma de matrices (esto es natural y no necesariamente realmente natural), podemos dibujar algunas matrices para encontrar una fórmula de derivación, luego podemos usar la potencia rápida de la matriz para encontrar Y
la imagen de arriba: el
emmm, ¿es un proceso de derivación?
código de CA es el siguiente :

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

Supongo que te gusta

Origin blog.csdn.net/qq_40924271/article/details/107879216
Recomendado
Clasificación