首先将2*k+1分解质因数,然后用天朝剩余定理合并答案。具体就是每个方程解的个数的乘积。
然后看方程x^a≡b(mod p^q)的解的个数,当b=0时:
x^a≡0(mod p^q),因此显然x必须是p^[q/a]的倍数,这里[x]表示x向上取整。那么就相当于统计0~p^q-1中p^[q/a]的倍数的个数;
x^a≡b(mod p^q),其中b=c*p^r,那么显然有a|r,否则无解;那么x应该为a'*p^(r/a)的形式,两边除以p^r后取指标变为a' lndx≡lndc(mod p^(q-r)),用BSGS得到indc进而得到答案。注意此时的答案并不是该方程的答案,因为x,x+p^(q-r),x+2*p^(q-r)都是原方程的答案,因此需要乘上p^(r-r/a)。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
#define N 100005
using namespace std;
int c[N];
int ksm(int x,int y){
int t=1; for (; y; y>>=1,x*=x) if (y&1) t*=x; return t;
}
int ksm_p(int x,int y,int p){
int t=1; for (; y; y>>=1,x=(ll)x*x%p) if (y&1) t=(ll)t*x%p; return t;
}
int gcd(int x,int y){ return (y)?gcd(y,x%y):x; }
int p_rt(int p){
int i,j,cnt=0,q=p-1;
for (i=2; i*i<=q; i++) if (!(q%i)){
c[++cnt]=i; if (i*i!=q) c[++cnt]=q/i;
}
for (i=2; i<p; i++){
for (j=1; j<=cnt; j++)
if (ksm_p(i,c[j],p)==1) break;
if (j>cnt) return i;
}
}
struct hash_cnt{
int tot,fst[100004],pnt[N],edg[N],nxt[N];
void clr(){
tot=0; memset(fst,0,sizeof(fst));
}
void ins(int x,int y){
int t=x%100003+1,p;
for (p=fst[t]; p; p=nxt[p]) if (pnt[p]==x) return;
pnt[++tot]=x; edg[tot]=y; nxt[tot]=fst[t]; fst[t]=tot;
}
int find(int x){
int t=x%100003+1,p;
for (p=fst[t]; p; p=nxt[p]) if (pnt[p]==x) return edg[p];
return 0;
}
}hsh;
int calc(int x,int y,int p,int q){
int mod=ksm(p,q); y%=mod;
if (!y) return ksm(p,q-(q-1)/x-1);
int cnt=0; for (; !(y%p); y/=p) cnt++;
if (cnt%x) return 0;
q-=cnt; cnt/=x; int phi=mod-mod/p,g=p_rt(p);
int m=(int)sqrt(mod)+1,now=1,i;
hsh.clr();
for (i=1; i<=m; i++){
now=(ll)now*g%mod; hsh.ins(now,i);
}
int w=ksm_p(now,phi-1,mod),k; now=y;
for (i=0; i<m; i++,now=(ll)now*w%mod)
if (k=hsh.find(now)) break;
int ind=i*m+k,d=gcd(x,phi);
return (ind%d)?0:d*ksm(p,(x-1)*cnt);
}
int main(){
int x,y,p,cas; scanf("%d",&cas);
while (cas--){
scanf("%d%d%d",&x,&y,&p); p=p<<1|1; int i,ans=1;
for (i=2; i*i<=p; i++) if (!(p%i)){
int cnt=0; for (; !(p%i); p/=i) cnt++;
if (ans) ans*=calc(x,y,i,cnt);
}
if (ans && p!=1) ans*=calc(x,y,p,1);
printf("%d\n",ans);
}
return 0;
}
by lych
2016.4.18