1 条题解

  • 0
    @ 2022-1-3 19:55:08

    更垃圾的阅读体验

    方法一

    Mod=2k+1Mod=2k+1,当 ModMod 不能被表示为 PqP^q 的形式时,考虑对其进行中国剩余定理分解为 piki\prod p_i^{k_i},那么只要对每个 pikip_i^{k_i} 分别处理出答案后直接乘起来就好了。

    问题转化求 xAB(modPq)x^A \equiv B \pmod{P^q} 的个数。

    分情况讨论一下。

    • B=0B=0

    假设 x=Pt×kx=P^t\times k,那么需要满足 AtqAt\ge q

    tqAt\ge \left\lceil\frac{q}{A}\right\rceil

    所以方程的解得个数为

    PqqAP^{q-\left\lceil\frac{q}{A}\right\rceil}
    • gcd(B,Pq)=1\gcd(B,P^q)=1

    aa 表示原根,设 B=ay,x=az,ϕ(Pq)=pB=a^y,x=a^z,\phi(P^q)=p

    所以 azAay(modp)a^{zA}\equiv a^y \pmod{p}

    此时可以求出 B=ayB=a^y,就直接解同余方程

    zAy(modp)zA\equiv y \pmod{p}

    先判断是否有解,如果有解,解的个数就是 gcd(A,p)\gcd(A,p)

    • gcd(B,Pq)>1\gcd(B,P^q)>1

    假设 B=PZ×bB=P^Z\times b

    那么

    xAPZ×b(modPq)x^A\equiv P^Z\times b \pmod{P^q}

    此时必然满足 ZZAA 的倍数,否则无解。

    转化为

    $$(\frac{x}{p^{\frac{Z}{A}}})^A\equiv b \pmod{P^{q-Z}} $$

    直接变成第二种情况。

    记住此时答案需要乘 PZZAP^{Z-\frac{Z}{A}}

    方法二

    上面一种方法的时间复杂度是 O(Tlognn)O(T\log n \sqrt{n}) 且常数比较大,原题可以过,但会被卡掉。

    考虑优化找 b=ayb=a^y 这个过程。

    考虑通过原根将 [0,p)[0,p) 放到一个圆上,圆上有 p1p-1 个值,Ai=aiA_i=a^i

    那么实际上只要找到 BB 在哪个位置就好了。

    但这十分困难,但我们有一个比较好求一点的,令 c=δp(B)c=\delta_p(B)

    那么 cc 有什么用呢?

    考虑 B0,B1,B2...B^0,B^1,B^2... 一共会在圆上占 cc 个位置,且这些位置均匀分布,所以可以求出两个位置之间的距离为 s=pcs=\frac{p}{c}

    B=aksB=a^{ks},那么必然满足 kkcc 的原根,不然不可能取到全部 cc 个点。

    然后就发现了一个重要结论,aka^k 也是原根,因为它也可以去到所有的点。

    那么直接令 aka^k 为新的原根,此时 y=sy=s

    然后就得到了一个 yy 直接求解就好了。


    代码
    #include<bits/stdc++.h>
    using namespace std;
    struct Prime{int p,pt,t;}a[50];//p表示素数,pt表示p^t,t表示P中含有多少个p
    int tot,_;
    void spilt(int p){
    	tot=0;
    	for(int i=2;i*i<=p;i++)
    		if(p%i==0){
    			a[++tot].p=i,a[tot].pt=1,a[tot].t=0;
    			for(;p%i==0;p/=i)a[tot].pt*=i,a[tot].t++;
    		}
    	if(p>1) a[tot].p=a[++tot].pt=p,a[tot].t=1;
    }
    int kuai(int a,int b,int mod){//快速幂
    	int ans=1;
    	for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;
    	return ans;
    }
    int get_Step(int a,int n,int mod){//求阶
    	int ans=n;
    	for(int i=2;i*i<=n;i++)
    		if(n%i==0){
    			while(ans%i==0&&kuai(a,ans/i,mod)==1)ans/=i;
    			for(;n%i==0;n/=i);
    		}
    	if(kuai(a,ans/n,mod)==1)ans/=n;
    	return ans;
    }
    int ans;
    void solve(int A,int B,int mod,int phi){
    	int c=get_Step(B,phi,mod),y=phi/c,G=__gcd(A,phi);
    	if(y%G)ans=0;
    	ans*=G;
    }
    int main(){
    	scanf("%d",&_);
    	while(_--){
    		int A,B,k;
    		scanf("%d%d%d",&A,&B,&k);
    		int P=2*k+1;
            B%=P;
    		ans=1;
    		spilt(P);//先将P分解质因数
    		for(int i=1;i<=tot;i++){
    			int p=a[i].p,t=a[i].t,pt=a[i].pt;
    			if(!ans)break;
    			if(B%pt==0) ans*=kuai(p,t-(t+A-1)/A,1e9);
    			else{
    				int Z=0,b=B;
    				for(;b%p==0;Z++,pt/=p,t--,b/=p);
    				if(Z%A)ans=0;
    				else{
    					solve(A,b,pt,pt-pt/p);
    					ans*=kuai(p,Z-Z/A,1e9);
    				}
    			}
    		}
    		printf("%d\n",ans);
    	}
    }
    
    • 1

    信息

    ID
    2219
    时间
    1000ms
    内存
    256MiB
    难度
    7
    标签
    (无)
    递交数
    19
    已通过
    9
    上传者