codevs 1281 Xn数列 快速幂+快速加防溢出

来源:互联网 发布:中囯邮政网络培训学院 编辑:程序博客网 时间:2024/06/05 00:37
题目描述 Description

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

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

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

输入描述 Input Description

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

输出描述 Output Description

输出一个数 Xn mod g

样例输入 Sample Input

11 8 7 1 5 3

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

int64按位相乘可以不要用高精度。

//long long的范围是-9*10^18到+9*10^18//小于等于10^18,所以两个数相加是不会超过long long滴,于是加个快速加即可 #include<cstdio>#include<iostream>#include<cstring>#define ll long longusing namespace std;ll ans[2][1],t[2][2],m,a,c,x0,n,g;ll fastadd(ll a,ll b){ll s=0;while(b){if(b&1) s=(s+a)%m;a=(a+a)%m;b>>=1;}return s;}void fastpow(){long long at[2][1],tt[2][2];//initt[0][0]=a%m,t[1][1]=1,t[0][1]=c%m,ans[0][0]=x0%m,ans[1][0]=1;while(n){if(n&1){memcpy(at,ans,sizeof(ans));memset(ans,0,sizeof(ans));for(int i=0;i<2;i++){for(int k=0;k<2;k++)ans[i][0]+=fastadd(t[i][k],at[k][0]);ans[i][0]%=m;}}memcpy(tt,t,sizeof(tt));memset(t,0,sizeof(t));for(int i=0;i<2;i++)for(int j=0;j<2;j++){for(int k=0;k<2;k++)t[i][j]+=fastadd(tt[i][k],tt[k][j]);t[i][j]%=m;}n>>=1;}}int main(){cin>>m>>a>>c>>x0>>n>>g;fastpow();cout<<ans[0][0]%g;return 0;}


1 0
原创粉丝点击