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按位相乘可以不要用高精度。
一开始推数学公式,求通项,但发现这并没有什么用,毕竟我不知道在除法情况下如何使用mod。。。
于是求助了一下,发现可以用矩阵+快速幂(按位乘)。
于是得到
a 1 和 x0
0 1 c
相乘就得到
x1
c
于是需要求得
a 1
0 1
的n次方。
题目提示,需要按位乘,那我们就按位乘好了,反正也容易。
不要忘了要用unsigned long long(被这个坑了两个点。。。)
code(有点乱):
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct aaa{
unsigned long long ju[2][2];
};
unsigned long long m,a,c,x0,n,g;
aaa quick(void);
aaa _mul(aaa a,aaa b);
unsigned long long mul(unsigned long long a,unsigned long long b);
int main()
{
cin>>m>>a>>c>>x0>>n>>g;
aaa k=quick();
unsigned long long ans=(mul(x0%m,k.ju[0][0])%m+mul(c%m,k.ju[0][1])%m)%m%g;
cout<<ans;
return 0;
}
aaa quick(void)
{
aaa base,ans;
base.ju[0][0]=a,base.ju[0][1]=1,base.ju[1][0]=0,base.ju[1][1]=1;
ans.ju[0][0]=1,ans.ju[0][1]=0,ans.ju[1][0]=0,ans.ju[1][1]=1;
while(n>0){
if(n&1){
ans=_mul(ans,base);
}
base=_mul(base,base);
n>>=1;
}
return ans;
}
aaa _mul(aaa a,aaa b)
{
aaa ans;
for(int i=0;i<=1;i++){
for(int j=0;j<=1;j++){
ans.ju[i][j]=(mul(a.ju[i][0],b.ju[0][j])+mul(a.ju[i][1],b.ju[1][j]))%m;
}
}
return ans;
}
unsigned long long mul(unsigned long long a,unsigned long long b)
{
unsigned long long ans=0;
while(b>0){
ans+=(a*(b%10))%m;
ans%=m;
b/=10;
a=a*10%m;
}
return ans;
}