bzoj 1467: Pku3243 clever Y (扩展BSGS)

来源:互联网 发布:ipad怎么清除应用数据 编辑:程序博客网 时间:2024/05/29 12:56

1467: Pku3243 clever Y

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 211  Solved: 113
[Submit][Status][Discuss]

Description

小Y发现,数学中有一个很有趣的式子: X^Y mod Z = K 给出X、Y、Z,我们都知道如何很快的计算K。但是如果给出X、Z、K,你是否知道如何快速的计算Y呢?

Input

本题由多组数据(不超过20组),每组测试数据包含一行三个整数X、Z、K(0 <= X, Z, K <= 109)。 输入文件一行由三个空格隔开的0结尾。

Output

对于每组数据:如果无解则输出一行No Solution,否则输出一行一个整数Y(0 <= Y < Z),使得其满足XY mod Z = K,如果有多个解输出最小的一个Y。

Sample Input

5 58 33
2 4 3
0 0 0

Sample Output

9
No Solution

HINT

Source

ghy



题解:



注:BSGS和扩展欧几里德的应用条件都是是A,P互质,那么这道题出来下面写出的麻烦的方法,还可以直接求

A^x-k=B*inv(A^k)  (mod p')  ,inv(A^k) 用扩展欧几里德来求。

#include<iostream>  #include<cstdio>  #include<cstring>  #include<cmath>  #include<algorithm>  #define ll long long  #define q 100003  using namespace std;  ll a,b,p,cnt,tot;  ll point[q<<1],v[q<<1],u[q<<1],next[q<<1];  void add(ll x,ll y)  {      ll k=x%q; tot++;      next[tot]=point[k];      u[tot]=x;      v[tot]=y;      point[k]=tot;  }  ll find(int x)//hash  {      ll k=x%q;      for (ll i=point[k];i;i=next[i])       if (u[i]==x)        return v[i];      return -1;  }  ll quickpow(ll num,ll x,ll m)//快速幂  {      ll ans=1; ll base=num%m;      while (x)      {          if (x&1)            ans=ans*base%m;          x>>=1;          base=base*base%m;      }      return ans%m;  }  ll gcd(ll x,ll y)//最大公约数  {      ll r;      while (y)       {          r=x%y;           x=y;           y=r;       }      return x;  }  ll exbsgs(ll a,ll b,ll p)  {      a%=p; b%=p;      if (b==1) return 0;      ll cnt=0,d=1,tmp=1;      while((tmp=gcd(a,p))!=1)//不断除以a,p的最大公约数,直到a,p互质      {          if (b%tmp)  return -1;          b/=tmp; p/=tmp; cnt++;          d=d*(a/tmp)%p;//记录的是A^x-cnt的系数          if (b==d) return cnt;      }      ll m=ceil(sqrt(p)); ll ans=b;  ll sum=1;      tot=0;      memset(point,0,sizeof(point));      memset(next,0,sizeof(next));      tmp=quickpow(a,m,p);      add(ans,0);      for (ll i=1;i<=m;i++)       ans=ans*a%p,add(ans,i);      for (ll i=1;i<=m+1;i++)       {          d=d*tmp%p;           ll t=find(d);           if (t!=-1)           return i*m-t+cnt;       }      return -1;  }  int main()  {      while (scanf("%I64d%I64d%I64d",&a,&p,&b))       {          if (a==0&&b==0&&p==0) break;          ll t=exbsgs(a,b,p);          if (t!=-1)           printf("%I64d\n",t);          else          printf("No Solution\n");       }  }



0 0