给定x,n,a,b,p,求1~x的闭区间里,满足\(n*a^n \equiv b(modp )\)的n有多少个
范围&性质 :\(\le p \le 10^6106+3, 1\le a,b\le p, 1\le x\le 10^{12}\) 保证p是质数。
观察数据范围,发现x过大,但是p只有1e6的大小,将突破口转向p
由于p是质数,所以存在如下的性质:
\(n\equiv n+p(mod p)\)
\(a^n\equiv a^{n+p-1}(mod p)\)
(原理可参考费马小定理)
我们发现\(a^n\)的出现具有周期性,考虑在[1,p-1]范围内枚举a的指数,我们设原式中的一次项为n,n可以表示为
同时n还有一个限制条件为
然后可以通过CRT合并同余方程,不过只有两个同余方程,CRT过于麻烦,综合两个条件我们可以构造出一个
新的通式
因此我们就枚举i,得到的n同时满足模p,p-1,且n出现的周期为\(p\times(p-1)\),所以用\((x-n)/(p\times(p-1)+1\)就是大小为n时解的个数
QED.
#include<bits/stdc++.h>
using namespace std;
namespace zzc
{
long long a,b,mod,x,ans=0;
long long qpow(long long x,long long y)
{
long long res=1;
while(y)
{
if(y&1) res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
void work()
{
scanf("%lld%lld%lld%lld",&a,&b,&mod,&x);
a=qpow(a,mod-2);
long long c=(mod-1)*mod;
for(long long i=1;i<=mod-1;i++)
{
b=b*a%mod;
long long tmp=(mod-1)*(i-b)+i;
tmp=(tmp%c+c)%c;
if(tmp<=x)
{
ans+=(x-tmp)/c+1;
}
}
printf("%lld",ans);
}
}
int main()
{
zzc::work();
return 0;
}
CF919E Congruence Equation (同余方程+构造)
原文:https://www.cnblogs.com/youth518/p/13649605.html