POJ3243:Clever Y——题解

http://poj.org/problem?id=3243

求最小的非负整数y满足x^y=k(mod z)

写完板子之后等待了半个小时poj才终于进入……

poj不行啊.jpg

以前一直觉得BSGS太神啦于是就跳了。

结果回头一看发现异常的简单。

(老年化初步体现flag*1)

首先x^y对k取模随着y的变化有周期性,最大周期不超过k(感性证明吧)

那么最小的y一定是在[0,k)之间了。

我们把这段区间分块,大小为n=sqrt(k),令m=k/n,则y=i*m-a,把y^a预处理移项到右面,hash表存一下就成了O(sqrt(k))的问题了。

是的就这么简单(当然如果存在gcd(x,k)!=1不存在逆元的话还得exgcd处理一下才行)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<cmath>
#include<stack>
using namespace std;
typedef long long ll;
const int N=999979;
const int M=50005;
struct HASH{
    int w,to,nxt;
}h[M];
int cnt,head[N];
inline void add(int x,int y){
    int t=x%N;
    for(int i=head[t];i;i=h[i].nxt){
        int v=h[i].to;
        if(v==x){
            h[i].w=y;//记大的 
            return;
        }
    }
    h[++cnt].to=x;h[cnt].w=y;h[cnt].nxt=head[t];head[t]=cnt;
}
inline int query(int x){
    int t=x%N;
    for(int i=head[t];i;i=h[i].nxt){
        int v=h[i].to;
        if(v==x)return h[i].w;
    }
    return -1;
}
int gcd(int a,int b){
    return (!b)?a:gcd(b,a%b);
}
int exgcd(int a,int b,int &x,int &y){
    if(!b){
        x=1,y=0;
        return a;
    }
    int ans=exgcd(b,a%b,y,x);
    y-=(ll)(a/b)*x;
    return ans;
}
int inv(int a,int c){
    int x,y;
    exgcd(a,c,x,y);
    return (x%c+c)%c;
}
//a^x=b(mod c);
int BSGS(int a,int b,int c){
    if(!a){
        if(!b)return 1;
        return -1;
    }
    int tot=0,g,d=1;
    while((g=gcd(a,c))!=1){
        if(b%g)return -1;
        ++tot;b/=g,c/=g;
        d=(ll)d*(a/g)%c;
    }
    b=(ll)b*inv(d,c)%c;
    cnt=0;memset(head,0,sizeof(head));
    int s=sqrt(c),p=1;
    for(int i=0;i<s;i++){
        if(p==b)return i+tot;
        add((ll)p*b%c,i);
        p=(ll)p*a%c;
    }
    int q=p;
    for(int i=s;i-s+1<c;i+=s){
        int t=query(q);
        if(t!=-1)return i-t+tot;
        q=(ll)q*p%c;
    }
    return -1;
}
int main(){
    int x,z,k;
    while(scanf("%d%d%d",&x,&z,&k)&&(ll)x+z+k>0){
        x%=z,k%=z;
        int ans=BSGS(x,k,z);
        if(ans==-1)puts("No Solution");
        else printf("%d
",ans);
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

原文地址:https://www.cnblogs.com/luyouqi233/p/8989786.html