BZOJ-2875 [Noi2012]随机数生成器(等比数列求和)
题目描述
给出 \(m,a,c,x_0\),按以下方式生成序列 \(\{x_i\}\):
\[x_{n+1}=(ax_n+c)\mod {m}
\]
求 \(x_n\mod g\)。
数据范围:\(m,a,c,n,x_0\leq 10^{18},1\leq g\leq 10^8,n,m\geq 1,a,c,x_0\geq 0\)。
分析
\[\begin{aligned}x_1&=a(x_0+c)\mod m\\
x_2&=(a(ax_0+c)+c)=a^2x_0+ac+c \mod m\\
x_3&=(a(ax_0+ac+c)+c)=a^3x_0+a^2c+ac+c\mod m\\
\cdots\\
x_n&=a^nx_0+c\sum_{i=0}^{n-1}a^i\mod m
\end{aligned}
\]
设公比为 \(q\) 的 \(n\) 项等比数列 \(1,q,q^2,\cdots,a^{n}\) 和为 \(S(n)\)。
若 \(n\) 为奇数:
\[\begin{aligned}&S(n)\\
=&1+q+q^2+\cdots+q^n\\
=&(1+q^{\frac{n}{2}+1})+q(1+q^{\frac{q}{2}+1})+q^2(1+q^{\frac{n}{2}+1})+\cdots +q^{\frac{n}{2}}(1+q^{\frac{n}{2}+1})\\
=&(1+q+q^2+\cdots+q^{\frac{n}{2}})(1+q^{\frac{n}{2}+1})\\
=&S(\frac{n}{2})(1+q^{\frac{n}{2}+1})
\end{aligned}
\]
若 \(n\) 为偶数:
\[\begin{aligned}&S(n)\\
=&1+q+q^2+\cdots+q^n\\
=&(1+q^{\frac{n}{2}+1})+q(1+q^{\frac{q}{2}+1})+q^2(1+q^{\frac{n}{2}+1})+\cdots +q^{\frac{n}{2}-1}(1+q^{\frac{n}{2}+1})+q^{\frac{n}{2}}\\
=&(1+q+q^2+\cdots+q^{\frac{n}{2}})(1+q^{\frac{n}{2}+1})+q^{\frac{n}{2}}\\
=&S(\frac{n}{2})(1+q^{\frac{n}{2}+1})+q^{\frac{n}{2}}
\end{aligned}
\]
代码
#include<bits/stdc++.h>
using namespace std;
long long m,a,c,x0,n,g;
long long quick_mul(long long a,long long b,long long mod)
{
long long ans=0;
while(b)
{
if(b&1)
ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans%mod;
}
long long quick_pow(long long a,long long b,long long mod)
{
long long ans=1;
while(b)
{
if(b&1)
ans=quick_mul(ans,a,mod)%mod;
a=quick_mul(a,a,mod)%mod;
b>>=1;
}
return ans%mod;
}
long long S(long long q,long long n)
{
if(n==0)
return 1;
if(n%2==1)
return quick_mul(S(q,n/2),1+quick_pow(q,n/2+1,m),m)%m;
else
return (quick_mul(S(q,n/2-1),1+quick_pow(q,n/2+1,m),m)+quick_pow(q,n/2,m))%m;
}
int main()
{
cin>>m>>a>>c>>x0>>n>>g;
long long ans=quick_pow(a,n,m);
ans=quick_mul(ans,x0,m);
ans=(ans+quick_mul(c,S(a,n-1),m))%m;
cout<<ans%g<<endl;
return 0;
}
posted on 2020-12-08 22:26 DestinHistoire 阅读(102) 评论(0) 编辑 收藏 举报