BZOJ2875//wikioi1281

来源:互联网 发布:win7安装windows live 编辑:程序博客网 时间:2024/06/06 20:13

给你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 longtypedef 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
原创粉丝点击