Description
Input
一行,六个整数,分别表示 x0, a, b, c, n, m。
Output
一行,一个整数,表示 xn mod m 的值。
Sample Input
1 1 1 1 5 1000000000
Sample Output
133904603
Data Constraint
分析:
前35%数据,直接暴力枚举即可,复杂度
。
另外35%数据,我们发现对 取模余数不同的数只有 个,一旦出现了一个相同的数就出现循环节,即可通过。注意循环节不一定从 开始,前面的一些数可能没有循环,要先减去。复杂度 。
最后30%数据,有
根据二次函数相关知识,化为顶点式,
由题意得, ,得
移项得,
假设数列 ,有 ,上式为,
两边同时乘 ,得
那么,
得,
因为 是质数,可以对指数模 。
复杂度
其实考场上觉得 这个条件很重要,对 想用原根了,其实也是可以做的,可以把乘法变为指数加法,设 ,那么每次相当于把指数乘2再加c,矩阵加速递推就可以了,这样复杂度是 。然后一开始没取模直接gg了。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
const int maxn=1e7+7;
using namespace std;
LL x,a,b,c,n,p,k;
LL A[maxn],B[maxn];
LL ksm(LL x,LL y,LL p)
{
if (y==1) return x;
LL c=ksm(x,y/2,p);
c=(c*c)%p;
if (y%2) c=(c*x)%p;
return c;
}
int main()
{
scanf("%lld%lld%lld%lld%lld%lld",&x,&a,&b,&c,&n,&p);
LL t=b/(2*a);
x%=p; a%=p; b%=p; c%=p;
if (n<=1e7)
{
for (int i=1;i<=n;i++) x=(a*x%p*x%p+b*x%p+c)%p;
printf("%lld",x);
}
else
{
if (p<=1e6)
{
A[0]=x;
B[x]=0;
for (int i=1;i<=n;i++)
{
x=(a*x%p*x%p+b*x%p+c)%p;
if (B[x]!=0)
{
k=i-B[x];
break;
}
A[i]=x;
B[x]=i;
}
n=(n-B[x])%k+B[x];
printf("%lld",A[n]);
}
else
{
LL d=ksm(2,n,p-1);
LL s=((d-1)+(p-1))%(p-1);
LL ans=(ksm(a,s,p)*ksm((x+t)%p,d,p)%p+p-t)%p;
printf("%lld",ans);
}
}
}