[NOI2012]随机数生成器(矩阵乘法+快速乘)

【题解】

矩阵乘法,但有陷阱:两个长整形相乘会溢出

因此它们相乘时用类似“快速幂”的“快速乘”解决(a*b=a*(b/2)*2 )


【代码】

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef long long LL;
LL m;
struct juzhen
{
	LL s[3][3];
	juzhen()
	{
		memset(s,0,sizeof(s));
	}
};
LL ksc(LL a,LL b)
{
	LL ans=0,count=a;
	for(;b>0;b/=2)
	{
		if(b&1) ans=(ans+count)%m;
		count=(count*2)%m;
	}
	return ans;
}
juzhen cheng(juzhen a,juzhen b)
{
	juzhen res;
	int i,j,k;
	for(i=1;i<=2;i++)
		for(j=1;j<=2;j++)
		{
			for(k=1;k<=2;k++)
				res.s[i][j]+=ksc(a.s[i][k],b.s[k][j]);
			res.s[i][j]%=m;	
		}
	return res;
}
juzhen ksm(juzhen a,LL n)
{
	juzhen res;
	if(n==1) return a;
	res=ksm(a,n/2);
	res=cheng(res,res);
	if(n%2==1) res=cheng(res,a);
	return res;
}
int main()
{
	juzhen Z,A;
	LL a,c,x0,n,g;
	scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&x0,&n,&g);
	A.s[1][1]=a;
	A.s[2][1]=c;
	A.s[2][2]=1;
	Z.s[1][1]=x0;
	Z.s[1][2]=1;
	A=ksm(A,n);
	Z=cheng(Z,A);
	printf("%lld",Z.s[1][1]%g);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值