1281 Xn数列
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 大师 Master
题目描述 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按位相乘可以不要用高精度。
中文题,不解释,主要是数据很吓人,一开始完全没注意溢出的问题,直接跪在了第二个点?然后注意了一些取模细节,跪在了第十个点= = 最后发现乘法都会溢出,改成了俄罗斯农民乘法,以为A了结果发现跪在了第五个点= =,后面才注意到最后乘常数又是直接乘的,所以有数据可以把这种方法搞掉,最后带×的都用俄罗斯农民乘法算,就A了= =。。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
long long mod,a,c,x0,n,g;
struct juzhen{
long long m[2][2];
};
long long modMul(long long a, long long b) {
long long res = 0LL;
for (; b; b >>= 1) {
if (b & 1) res = (res + a) % mod;
a = (a + a) % mod;
}
return res;
}
juzhen mut(juzhen a,juzhen b)
{
juzhen c;
for(int i=0;i<2;i++) {
for(int j=0;j<2;j++) {
c.m[i][j]=0;
for(int k=0;k<2;k++) {
c.m[i][j] += modMul(a.m[i][k], b.m[k][j]);
c.m[i][j] %= mod;
}
}
}
return c;
}
juzhen power(juzhen a,long long p)
{
juzhen ans;
memset(ans.m,0,sizeof(ans.m));
for(int i=0;i<2;i++) {
ans.m[i][i]=1;
}
while(p) {
if(p&1)
ans=mut(ans,a);
a=mut(a,a);
p>>=1;
}
return ans;
}
int main()
{
cin>>mod>>a>>c>>x0>>n>>g;
juzhen ans;
a %= mod;
c %= mod;
x0 %= mod;
ans.m[0][0] = a;
ans.m[0][1] = ans.m[1][1] = 1;
ans.m[1][0] = 0;
ans = power(ans,n);
long long res = (modMul(ans.m[0][0], x0) + modMul(ans.m[0][1], c) ) % mod;
cout << res % g << endl;
return 0;
}