CF919E Congruence Equation (同余方程+构造)

题意:

给定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是质数,所以存在如下的性质:

  1. \(n\equiv n+p(mod p)\)

  2. \(a^n\equiv a^{n+p-1}(mod p)\)

    (原理可参考费马小定理)

    我们发现\(a^n\)的出现具有周期性,考虑在[1,p-1]范围内枚举a的指数,我们设原式中的一次项为n,n可以表示为

    \[n \equiv b\times inv(a^i)(mod p) \]

    同时n还有一个限制条件为

    \[n \equiv i (mod (p-1)) \]

    然后可以通过CRT合并同余方程,不过只有两个同余方程,CRT过于麻烦,综合两个条件我们可以构造出一个

新的通式

\[n = (p-1)\times(i-b\times inv(a^i))+i \]

因此我们就枚举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;
}
posted @ 2020-09-11 08:18  youth518  阅读(193)  评论(0编辑  收藏  举报