题目分析

题目要求 $x^A \equiv B \pmod{P}$的解的个数。

首先将 $P$分解质因数,对于每个方程 $x^A \equiv b_i \pmod{p_i^{a_i}}$,求出解的个数。假设我们确定了这个方程的解,最后用中国剩余定理合并,不同方程组肯定对应不同的解,所以将每个方程的解数乘起来就是最终解的个数。

对于单个方程,分三种情况讨论。

情况 1:$b_i=0$。

说明若将 $x$写成 $p^tq$的形式,$t$因子的大小至少是 $\lceil \frac{a}{A} \rceil$,那么 $q$的大小就可以取 $[1,p^{a-(\lceil \frac{a}{A} \rceil)}]$,并且其中一些取值有 $p$因子所以也会包括 $t$取更大的值的情况,所以该情况下的解数是 $p^{a-(\lceil \frac{a}{A} \rceil)}$

情况 2:$p|b$

设 $b=p^td$,则 $x^A \equiv p^td \pmod{p^a}$。若 $A \not| t$,则无解,否则

$$(\frac{x}{p^{\frac{t}{A}}})^A \equiv d \pmod{p^{a-t}}$$

就转化成情况 3 了。

但是在情况 2 中,本来 $\frac{x}{p^{\frac{t}{A}}}$的取值范围是 $[0,p^{a-\frac{t}{A}})$的,所以解数还要乘一个 $p^{t-\frac{t}{A}}$

情况 3:$p \not| b$

求出 $p^a$的原根 $g$($p^a$不是质数啊,剩余系大小是 $\phi(p^a)$啊 QAQ)

那么让 $g^r \equiv b \pmod{p^a}$,$r$用 BSGS 求出,则根据欧拉降幂得出下面的式子,原 $x$的解数是下面这个式子的解数:

$Ax \equiv r \pmod{p^a \bmod{\phi(p^a)}}$

后面那一串记作 $p’$吧。

那么这个式子,若 $gcd(p’,A) \not| r$,无解,否则根据同余方程通解的表现形式(解出的任意 $x$,$x+t\frac{p’}{gcd(p’,A)}$),解数为 $gcd(p’,A)$。

代码

#include<bits/stdc++.h>
using namespace std;
#define RI register int
int T,A,B,P,kP,ans;
int pri[100005];

int gcd(int x,int y) {return y?gcd(y,x%y):x;}
int fast_pow(int x,int y) {
    int re=1;
    for(;y;y>>=1,x=x*x) if(y&1) re=re*x;
    return re;
}
int fast_pow(int x,int y,int p) {
    int re=1;
    for(;y;y>>=1,x=1LL*x*x%p) if(y&1) re=1LL*re*x%p;
    return re;
}
map<int,int> mp;
int bsgs(int x,int y,int p) {
    if(y==1) return 0;
    mp.clear();int m=ceil(sqrt((double)p)),q=1;
    for(RI i=0;i<m;++i) mp[(int)(1LL*q*y%p)]=i+1,q=1LL*q*x%p;
    for(RI i=m,x=1;;i+=m) {
        x=1LL*x*q%p;
        if(mp[x]) return i-mp[x]+1;
        if(i>p) return -1;
    }
}
int getg(int x,int phi) {
    int js=0,kphi=phi;
    for(RI i=2;i*i<=kphi;++i)
        if(kphi%i==0) {pri[++js]=i;while(kphi%i==0) kphi/=i;}
    if(kphi!=1) pri[++js]=kphi;
    for(RI i=2;;++i) {
        int flag=1;
        if(fast_pow(i,phi,x)!=1) continue;
        for(RI j=1;j<=js;++j)
            if(fast_pow(i,phi/pri[j],x)==1) {flag=0;break;}
        if(flag) return i;
    }
}
int getans(int p,int a,int kB) {
    if(kB==0) return fast_pow(p,a-((a-1)/A+1));
    int t=0;while(kB%p==0) kB/=p,++t;
    if(t%A) return 0;
    a-=t;int pa=fast_pow(p,a);
    int phi=pa-pa/p,g=getg(pa,phi),r=bsgs(g,kB,pa),d=gcd(phi,A);
    if(r%d) return 0;
    return d*fast_pow(p,t-t/A);
}

int main()
{
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d%d",&A,&B,&P);
        P=P+P+1,kP=P,ans=1;
        for(RI i=2;i*i<=kP;++i) if(kP%i==0) {
            int js=0,pa=1;
            while(kP%i==0) kP/=i,++js,pa*=i;
            ans*=getans(i,js,B%pa);
        }
        if(kP!=1) ans*=getans(kP,1,B%kP);
        printf("%d\n",ans);
    }
    return 0;
}
分类: 文章

litble

苟...苟活者在淡红的血色中,会依稀看见微茫的希望

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注