BZOJ 2219: 数论之神

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2219

N次剩余+CRT。。。

就是各种奇怪的分类讨论。。

#include<cstring>
#include<iostream>
#include<cstdio>
#include<map>
#include<cmath>
#include<algorithm>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 50050
#define inf 2000000000
using namespace std;
int a,b,k,p,t,ans;
map<int,int> mp;
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int Pow(int x,int y){
    int ans=1;
    while (y){
        if (y&1) ans=1LL*ans*x;
        x=1LL*x*x; y>>=1;
    }
    return ans;
}
int Pow(int x,int y,int mo){
    int ans=1; while (y){
        if (y&1) ans=1LL*ans*x%mo;
        x=1LL*x*x%mo; y>>=1;
    }
    return ans;
}
int divs[maxn],dtot;
int groot(int p){//是对于p-1的每一个素因子a去检查(p-1)/a!! 
    dtot=0;
    int q=p-1;
    for (int i=2;i*i<=q;i++){
        if (q%i==0) {
            divs[++dtot]=i;
            if (i*i!=q) divs[++dtot]=q/i;
        }
    }
    for (int i=2;i<p;i++){
        int ok=0;
        rep(j,1,dtot) if (Pow(i,divs[j],p)==1) {ok=1;break;}
        if (!ok) return i;
    }
}
int exgcd(int a,int b,int &x,int &y){
    if (b==0) {
        x=1; y=0; return a;
    }
    int d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
int gcd(int a,int b){
    if (b==0) return a;
    return gcd(b,a%b);
}
int NI(int a,int b){
    int x,y; 
    exgcd(a,b,x,y);
    return (x%b+b)%b;
}
int bsgs(int a,int b,int p){
    mp.clear();
    int m=sqrt(p)+1,mul,tmp;
    int now=1; rep(i,0,m-1) {if (!mp.count(now)) mp[now]=i; now=1LL*now*a%p;}
    now=1; mul=Pow(a,m,p);
    rep(i,0,m-1){
        tmp=1LL*b*NI(now,p)%p;
        if (mp.count(tmp)) return mp[tmp]+i*m;
        now=1LL*now*mul%p;
        if (now==0) break;
    } 
    return inf;
}
int solve(int a,int b,int p,int d){
    int pd=Pow(p,d);
    b=b%pd;
    if (b==0) return Pow(p,d-((d-1)/a+1));
    else {
        int bet=0;        
        while (b%p==0) bet++,b/=p;
        if (bet%a!=0) return 0;
        int tt=bet/a;
        int g=groot(p),phi=pd-pd/p;
        int ind=bsgs(g,b,pd);
        int d=gcd(a,phi);
        if (ind%d==0) return d*Pow(p,(a-1)*tt);
        else return 0;
    }    
}
int main(){
    t=read();
    while (t--){
        a=read(); b=read(); k=read();
        p=2*k+1;
        ans=1;
        for (int i=2;i*i<=p&&ans;i++) if ((p%i)==0) {
            int now=0; while ((p%i)==0) p/=i,now++;
            ans=ans*solve(a,b,i,now);
        }
        if (p!=1&&ans) ans=ans*solve(a,b,p,1); 
        printf("%d\n",ans);
    }
    return 0;
} 

 

posted on 2016-01-10 21:15  ctlchild  阅读(370)  评论(0编辑  收藏  举报

导航