bzoj2219 数论之神
作者:互联网
直接考虑\(x^A\equiv B\pmod{p^c}\),其中\(\gcd(B,p^c)\neq1,B\neq0\)的情况。
分解为\((p^t\cdot h)^A\equiv p^kb\pmod{p^c}\),那么必须有\(A|k\),否则无解。
要求\(tA=k\),那么方程变成\(h^A\equiv b\pmod{p^{c-k}}\)。解出来\(h\)之后他是模\(p^{c-k}\)意义下的,但是实际上\(h\)是在模\(p^{c-\frac{k}{A}}\)意义下的。所以每个解出来的\(h\)都对应\(p^{k-\frac{k}{A}}\)个原方程的值。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define N 1000002
int T,prim[N],cnt,A,B,p,b[N],ci[N],tot,G,pi,fp;
int bb[N],tt;
bool isp[N];
map<int,int>mp;
int gcd(int x,int y){return y==0?x:gcd(y,x%y);}
void exgcd(int a,int b,ll &x,ll &y)
{if(b==0){x=1;y=0;return;}exgcd(b,a%b,x,y);ll t=y;y=x-a/b*y;x=t;}
inline int inv(int x)
{ll tx,ty;exgcd(x,pi,tx,ty);tx=(tx%pi+pi)%pi;return tx;}
inline int bsgs(int x)
{if(x==1)return 0;
mp.clear();int tv=1;mp[1]=0;int sqr=sqrt(fp);
for(int i=1;i<=sqr;i++)
{
tv=1ll*tv*G%pi;
if(!mp.count(tv))mp[tv]=i;
if(tv==x)return i;
}int iv=inv(tv);
for(int i=1;i<=sqr;i++)
{
x=1ll*x*iv%pi;
if(mp.count(x))return i*sqr+mp[x];
}
}
inline int ksm(int d,int k,int tp)
{int ret=1;while(k){if(k&1)ret=1ll*ret*d%tp;d=1ll*d*d%tp;k>>=1;}return ret;}
inline int cal(int x)
{
pi=1;for(int i=0;i<ci[x];i++)pi*=b[x];int tB=B%pi;
fp=pi/b[x]*(b[x]-1);tt=0;
for(int i=1;i*i<=fp;i++)if(fp%i==0)bb[++tt]=i,bb[++tt]=fp/i;
for(G=2;G<=100;G++)
{int i;
for(i=1;i<=tt;i++)if(bb[i]!=fp&&ksm(G,bb[i],pi)==1)break;
if(i>tt)break;
}
if(!tB)
{
int tp=ci[x]/A;if(ci[x]%A)tp++;
int ret=1;for(int j=0;j<tp;j++)ret*=b[x];
return pi/ret;
}
if(gcd(tB,pi)==1)
{
int tb=bsgs(tB);
int td=gcd(fp,A);
if(tb%td)return 0;
return td;
}
int k=0,b2=tB;while(b2%b[x]==0)k++,b2/=b[x];
if(k%A)return 0;
for(int i=0;i<k;i++)pi/=b[x];
fp=pi/b[x]*(b[x]-1);
int tb=bsgs(b2);
int td=gcd(fp,A);
if(tb%td)return 0;
for(int i=0;i<k-k/A;i++)td=td*b[x];
return td;
}
int main()
{
for(int i=2;i<=1000000;i++)isp[i]=1;
for(int i=2;i<=1000000;i++)
{if(isp[i])prim[++cnt]=i;
for(int j=1;j<=cnt&&prim[j]*i<=1000000;j++)
{isp[prim[j]*i]=0;if(i%prim[j]==0)break;}
}
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&A,&B,&p);p=p<<1|1;tot=0;int tp=p;
for(int i=1;i<=cnt&&prim[i]<=tp;i++)
{
if(tp%prim[i]==0)
{
b[++tot]=prim[i];ci[tot]=0;
while(tp%prim[i]==0)ci[tot]++,tp/=prim[i];
}
}if(tp>1)b[++tot]=tp,ci[tot]=1;int ans=1;
for(int i=1;i<=tot;i++)ans*=cal(i);
printf("%d\n",ans);
}
}
标签:ci,pi,return,数论,ll,bzoj2219,int,include,之神 来源: https://www.cnblogs.com/LebronDurant/p/14515458.html