题解 P2044 【[NOI2012]随机数生成器】
着重介绍一下求数列通项的不动点法。
形如
设不动点为
于是
这样
接下来的问题是如何求
展开得
只要求
递归求解即可。其中乘法部分要用龟速乘。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<math.h>
using namespace std;
long long mod,n,a,c,x,g;
long long mul(long long x,long long y)
{
long long ret=0,bas=x;
while(y)
{
if(y&1)
{
ret+=bas;
if(ret>=mod) ret-=mod;
}
bas+=bas;if(bas>=mod) bas-=mod;
y>>=1;
}
return ret;
}
long long F_p(long long x,long long y)
{
long long ret=1,bas=x;
while(y)
{
if(y&1) ret=mul(ret,bas);
bas=mul(bas,bas);
y>>=1;
}
return ret;
}
long long solve(long long mx)
{
if(!mx) return 1;
long long tt=solve(mx>>1);
long long pp=mul(tt,F_p(a,(mx>>1)+1));
tt+=pp;if(tt>=mod) tt-=mod;
if(!(mx&1))
{
tt-=F_p(a,mx+1);
if(tt<0) tt+=mod;
}
return tt;
}
int main()
{
scanf("%lld%lld%lld%lld%lld%lld",&mod,&a,&c,&x,&n,&g);
a%=mod,c%=mod,x%=mod;
long long fz=solve(n-1);
fz=mul(fz,c);
x=mul(x,F_p(a,n));
x+=fz;if(x>=mod) x-=mod;
printf("%lld\n",x%g);
return 0;
}