P1707 刷题比赛

$ color{#0066ff}{ 题目描述 }$

洛谷OJ当然算是好地方,nodgd同学打算和朋友分享一下。于是他就拉上了他的朋友Ciocio和Nicole两位同学一起刷题。喜欢比赛的他们当然不放过这样一次刷题比赛的机会!

在第1天nodgd,Coicoi,Nicole都只做了1道题。

在第2天nodgd,Coicoi,Nicole都只做了3道题。

他们都有着严格的刷题规则,并且会在每一天都很遵守规则的刷一定量的题。

(1)nodgd同学第k+2天刷题数量a[k+2]=p*a[k+1]+q*a[k]+b[k+1]+c[k+1]+r*k^2+t*k+1;

(2)Ciocio同学第k+2天刷题数量b[k+2]=u*b[k+1]+v*b[k]+a[k+1]+c[k+1]+w^k;

(3)Nicole同学第k+2天刷题数量c[k+2]=x*c[k+1]+y*c[k]+a[k+1]+b[k+1]+z^k+k+2;

(以上的字母p,q,r,t,u,v,w,x,y,z都是给定的常数,并保证是正整数)

于是他们开始了长时间的刷题比赛!一共进行了N天(4<=N<=10^16)

但是时间是可贵的,nodgd想快速知道第N天每个人的刷题数量。不过nodgd同学还有大量的数学竞赛题、物理竞赛题、英语竞赛题、美术竞赛题、体育竞赛题……要做,就拜托你来帮他算算了。

由于结果很大,输出结果mod K的值即可。

(color{#0066ff}{输入格式})

第一行两个正整数N,K。(4<=N<=10^16,2<=K<=10^16)

第二行四个正整数p,q,r,t。

第三行三个正整数u,v,w。

第四行三个正整数x,y,z。

(保证p,q,r,t,u,v,w,x,y,z都是不超过100的正整数)

(color{#0066ff}{输出格式})

共三行,每行一个名字+一个空格+一个整数。依次是nodgd,Ciocio,Nicole和他们在第N天刷题数量mod K的值。

(color{#0066ff}{输入样例})

4 10007
2 1 1 1
2 2 3
1 1 2

(color{#0066ff}{输出样例})

nodgd 74
Ciocio 80
Nicole 59

(color{#0066ff}{数据范围与提示})

矩阵乘法。

注意,中间相乘过程可能会比64位长整型的数据范围还要大。

(color{#0066ff}{题解})

啊啊啊啊恶心!!

没啥可说的,推矩阵(退役)吧

注意转移要龟乘!

矩阵位置对应(a[k+1],a[k],b[k+1],b[k],c[k+1],c[k],k^2,k,1,w^k,z^k)

蜜汁转移。。。

初始矩阵就是(3,1,3,1,3,1,1,1,1,w,z)

#include<bits/stdc++.h>
#define LL long long
LL in() {
	char ch; LL x = 0, f = 1;
	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
	return x * f;
}
LL n, mod;
LL msc(LL x, LL y) {
	LL re = 0;
	while(y) {
		if(y & 1) re = (re + x) % mod;
		x = (x + x) % mod;
		y >>= 1;
	}
	return re;
}

struct node {
	LL ju[15][15];
	node() { memset(ju, 0, sizeof ju); }
	void e() {
		memset(ju, 0, sizeof ju);
		for(int i = 1; i <= 11; i++) ju[i][i] = 1;
	}
	friend node operator * (const node &a, const node &b) {
		node t;
		for(int i = 1; i <= 11; i++)
			for(int j = 1; j <= 11; j++)
				for(int k = 1; k <= 11; k++)
					(t.ju[i][j] += msc(a.ju[i][k], b.ju[k][j])) %= mod;
		return t;
	}
	node ksm(LL y) {
		node re, x = *this;
		re.e();
		while(y) {
			if(y & 1) re = re * x;
			x = x * x;
			y >>= 1;
		}
		return re;
	}
}beg, A;
int tmp[12][12] = {
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
	{0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 1, 0, 2, 1, 0, 0, 0},
	{0, 1, 0, 0, 0, 2, 0, 1, 1, 1, 0, 0},
	{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
};
int lsbeg[] = {0, 3, 1, 3, 1, 3, 1, 1, 1, 1, 0, 0};

int main() {
	n = in(), mod = in();
	LL w, z;
	tmp[1][1] = in();  //p
	tmp[2][1] = in();  //q
	tmp[7][1] = in();  //r
	tmp[8][1] = in();  //t
	tmp[3][3] = in();  //u
	tmp[4][3] = in();  //v
	w = tmp[10][10] = in();//w
	tmp[5][5] = in();  //x
	tmp[6][5] = in();  //y
	z = tmp[11][11] = in();//z
	lsbeg[10] = w, lsbeg[11] = z;
	for(int i = 1; i <= 11; i++) beg.ju[1][i] = lsbeg[i];
	for(int i = 1; i <= 11; i++)
		for(int j = 1; j <= 11; j++)
			A.ju[i][j] = tmp[i][j];
	beg = beg * A.ksm(n - 2);
	printf("nodgd %lld
Ciocio %lld
Nicole %lld
", beg.ju[1][1], beg.ju[1][3], beg.ju[1][5]);
	return 0;
}
原文地址:https://www.cnblogs.com/olinr/p/10533070.html