2875: [Noi2012]随机数生成器

2875: [Noi2012]随机数生成器

Time Limit: 10 Sec   Memory Limit: 512 MB
Submit: 1543   Solved: 863
[ Submit][ Status][ Discuss]

Description

Input

包含6个用空格分割的m,a,c,X0,n和g,其中a,c,X0是非负整数,m,n,g是正整数。

Output

输出一个数,即Xn mod g

Sample Input


11 8 7 1 5 3


Sample Output

2

HINT

Source

[ Submit][ Status][ Discuss]
嗯。。矩阵乘法快速幂秒过的题 等等。。模数这么大乘法会爆啊。。这不是要高精?(WA*1) 不对啊乘法可以用log次加法替代。。(我信仰帅哥副队) 不对啊"快速加法"应该都是加号啊。。。(WA*2)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

typedef long long LL;

LL s[3],a,m,n,mo,g,ans[3];

LL Add(LL x,LL y)
{
	LL ret = 0;
	for (; y; y >>= 1) {
		if (y & 1) ret = (ret + x)%mo;
		x = (x + x)%mo; 
	}
	return ret;
}

struct data{
	LL b[3][3];
	data() {memset(b,0,sizeof(b));}
	
	data operator * (const data &d) {
		data c;
		for (int i = 1; i <= 2; i++)
			for (int j = 1; j <= 2; j++)
				for (int l = 1; l <= 2; l++)
					c.b[i][j] = (c.b[i][j] + Add(b[i][l],d.b[l][j]))%mo;
		return c;
	}
};

data ksm(LL y)
{
	data ret,now;
	ret.b[1][1] = ret.b[2][2] = 1;
	now.b[1][1] = a; now.b[2][1] = now.b[2][2] = 1; now.b[1][2] = 0;
	for (; y; y >>= 1) {
		if (y & 1) ret = ret*now;
		now = now*now;
	}
	return ret;
}

LL getLL()
{
	LL ret = 0;
	char ch = getchar();
	while (ch < '0' || '9' < ch) ch = getchar();
	while ('0' <= ch && ch <= '9') ret = ret*10 + 1LL*(ch - '0'),ch = getchar();
	return ret;
}

int main()
{
	#ifdef YZY
		freopen("yzy.txt","r",stdin);
	#endif
	
	mo = getLL(); a = getLL(); s[2] = getLL(); 
	s[1] = getLL(); n = getLL(); g = getLL();
	data ret = ksm(n);
	for (int i = 1; i <= 2; i++)
		for (int j = 1; j <= 2; j++)
			ans[i] = (ans[i] + Add(s[j],ret.b[j][i]))%mo;
	cout << ans[1]%g;
	return 0;
}




你可能感兴趣的:(2875: [Noi2012]随机数生成器)