题解 P1707 【刷题比赛】

原题地址P1707刷题比赛

由题意显然,此题为一道矩阵乘法题,已知两个矩阵求得一个未知矩阵的过程,根据题意我们可得需要来维护11个项来进行计算,则状态转移矩阵为一个\(11 * 11\)的的矩阵,初始矩阵为

\(a_{k+1}\) \(a_k\) \(b_{k+1}\) \(b_k\) \(c_{k+1}\) \(c_k\) \(k^2\) \(k\) \(w^k\) \(z^k\) \(1\)
所经过转以后得到的矩阵为
\(a_{k+2}\) \(a_{k+1}\) \(b_{k+2}\) \(b_{k+1}\) \(c_{k+2}\) \(c_{k+1}\) \((k+1)^2\) \(k+1\) \(w^{k+1}\) \(z^{k+1}\) \(1\)
-----------: -----------: -----------: -----------: -----------: -----------: -----------: -----------: -----------: -----------: -----------:
通过矩阵乘法可得转移矩阵为

然后考虑去求即可,数据很大所以考虑用慢速乘即可

应当注意的细节

1,矩阵乘法不满足交换律,所以在相乘时应当有所注意

2,重载运算符建议封装,这样可以在多个矩阵相乘时减少不必要的代码量

3,注意\(k\)变为\(k+1\),\(k^2\)变为\((k+1)^2\)时候的细节,比较容易出错

\(Code\):

#include<bits/stdc++.h>

#define LL long long

/*呐,这份感情,什么时候能传达到呢*/

using namespace std;

template <typename T> void read(T & t){
	t = 0;int f = 1;char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-')f =- 1;ch = getchar();}
	do{t = t * 10 + ch - '0';ch = getchar();}while(ch >= '0' && ch <= '9');t *= f;
}

LL n , m;

LL p , q , r , t;

LL u , v , w , x , y , z;

inline LL mul(LL x , LL y){
	LL res = 0;
	for(; y ; y >>= 1 , x = (x + x) % m){
		if(y & 1){
			res = (res + x) % m;
		}
	}
	return res;
}

struct node{
	LL yuni[12][12];
	
	friend node operator * (const node &a , const node &b){
		node c;
		for(int i = 1;i <= 11;i ++){
			for(int j = 1;j <= 11;j ++){
				c.yuni[i][j] = 0;
				for(int k = 1;k <= 11;k ++){
					c.yuni[i][j] = (c.yuni[i][j] + mul(a.yuni[i][k] , b.yuni[k][j])) % m;
				}
			}
		}
		return c;
	}
}ans , abi;


inline void quick_pow(LL b){
    for(; b ; b >>= 1 , abi = abi * abi){
		if(b & 1){
			ans = abi * ans;
		}
	}
}

/*inline void quick_pow(LL b){
	while(b > 0){
   		if(b & 1){
   			ans = abi * ans;
   		}
		abi = abi * abi;
   		b >>= 1;
	}
}*/

inline void build(){
	abi.yuni[1][1] = p , abi.yuni[1][2] = q , abi.yuni[1][3] = 1 , abi.yuni[1][5] = 1 , abi.yuni[1][7] = r , abi.yuni[1][8] = t , abi.yuni[1][11] = 1;	
	abi.yuni[2][1] = 1;
	abi.yuni[3][1] = 1 , abi.yuni[3][3] = u , abi.yuni[3][4] = v , abi.yuni[3][5] = 1 , abi.yuni[3][9] = 1;
	abi.yuni[4][3] = 1;
	abi.yuni[5][1] = 1 , abi.yuni[5][3] = 1 , abi.yuni[5][5] = x , abi.yuni[5][6] = y , abi.yuni[5][8] = 1 , abi.yuni[5][10] = 1 , abi.yuni[5][11] = 2;
	abi.yuni[6][5] = 1;
	abi.yuni[7][7] = 1 , abi.yuni[7][8] = 2 , abi.yuni[7][11] = 1;
	abi.yuni[8][8] = 1 , abi.yuni[8][11] = 1;
	abi.yuni[9][9] = w;
	abi.yuni[10][10] = z;
	abi.yuni[11][11] = 1;
}

int main(){
	read(n);read(m);
	read(p);read(q);read(r);read(t);
	read(u);read(v);read(w);
	read(x);read(y);read(z);
	build();
	ans.yuni[1][1] = ans.yuni[3][1] = ans.yuni[5][1] = 3;
	ans.yuni[2][1] = ans.yuni[4][1] = ans.yuni[6][1] = ans.yuni[8][1] = ans.yuni[11][1] = 1;
	ans.yuni[7][1] = 1 , ans.yuni[9][1] = w % m , ans.yuni[10][1] = z % m;
	quick_pow(n - 2);
	printf("nodgd %lld\n" , ans.yuni[1][1]);
	printf("Ciocio %lld\n" , ans.yuni[3][1]);
	printf("Nicole %lld\n" , ans.yuni[5][1]);
	return 0;
}

有错误欢迎指出

posted @ 2020-07-14 08:12  Ame_sora  阅读(116)  评论(0编辑  收藏  举报