BZOJ2875//wikioi1281

给你6个数,m, a, c, x0, n, g

Xn+1 = ( aXn + c ) mod m,求Xn

m, a, c, x0, n, g<=10^18

一行六个数 m, a, c, x0, n, g

输出一个数 Xn mod g

11 8 7 1 5 3

2


建构一个矩阵,利用矩阵预算求解这个不难(具体看代码),关键在于两数相乘是会超LL范围;

所以这里介绍一种快速幂求乘法:

a,b是两个要相乘的数,

 循环是b/2,a*2(使积不变)如果b&1==1,则需要累加一个这一时段的a值;

 ll mul(ll a,ll b){
ll ans=0;
for(;b;b>>=1,(a<<=1)%=P)
if(b&1) (ans+=a)%=P;
return ans;
}


#include<cstdio>
#include<cstring> 
#define LL long long
typedef long long ok[3][3];
LL m,a,c,g,n,x,tot;
ok ans={0},w,f,w2;
LL mul(LL x,LL y)
{
	LL answ=0;
	for(;y;y>>=1,(x<<=1)%=m)
	 if(y&1)(answ+=x)%=m;
	return answ;
}
void ma(ok &t)
{
	memcpy(w,t,sizeof(w));
	memcpy(w2,f,sizeof(w2));
	for(int i=1;i<=2;i++)
	 for(int j=1;j<=2;j++)
	 {
	  t[i][j]=0;
	  for(int k=1;k<=2;k++)
	   t[i][j]=(t[i][j]+mul(w[i][k],w2[k][j]))%m;
	 }  
}
int main()
{
	scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&x,&n,&g);
	f[1][1]=a%m;f[1][2]=0;
	f[2][1]=f[2][2]=1;
	for(int i=1;i<=2;i++)ans[i][i]=1;
	while(n)
	{
		if(n&1)ma(ans);
		n>>=1;
		ma(f);
	}
	tot=(mul(ans[1][1],x%m)+mul(ans[2][1],c%m))%m;
	printf("%lld\n",tot%g);
	//for(;;);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值