其他分享
首页 > 其他分享> > bzoj2219 数论之神

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