【bzoj 1467】Pku3243 clever Y

1467: Pku3243 clever Y

Time Limit: 4 Sec Memory Limit: 64 MB
Submit: 213 Solved: 115
[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模板题】
【扩展BSGS】
[http://blog.csdn.net/reverie_mjp/article/details/51233630]

#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
map<ll,bool>h1;
map<ll,ll>hash;
ll n,m,p,ans;
ll gcd(ll a,ll b)
{
    if(!(a%b)) return b;
     else return gcd(b,a%b);
}
ll poww(ll x,ll q,ll mod)
{
    ll sum=1;
    for(;q;q>>=1,x=x*x%mod)
     if(q&1)  sum=sum*x%mod;
    return sum;  
}
ll exbsgs(ll x,ll y,ll mod)
{
    x%=mod,y%=mod;
    if(y==1) return 0;
    ll t=1,d=1,k=0;
    while((t=gcd(x,mod))!=1)
     {
        if(y%t) return -1;
        k++;
        y/=t; mod/=t;
        d=d*(x/t)%mod;
        if(y==d) return k;
     }//删公因数 
    h1.clear(); hash.clear();
    ll mm=ceil(sqrt((double)mod));
    ll sum=poww(x,mm,mod);
    ll l=y; hash[l]=0; h1[l]=true;
    for(ll i=1;i<=mm;++i)
      {
        l=l*x%mod;
        hash[l]=i;
        h1[l]=true;
      }    
    for(ll i=1;i<=mm;++i)
     {
        d=d*sum%mod;
        if(h1[d]) return i*mm-hash[d]+k;
     }//BSGS 
    return -1;
}
int main()
{
    while(~(scanf("%lld%lld%lld",&n,&p,&m)))
     {
        if(!n&&!m&&!p) return 0;
        ans=exbsgs(n,m,p);
        if(ans==-1) printf("No Solution\n");
         else printf("%lld\n",ans);
     }
    return 0;
}

你可能感兴趣的:(bzoj,扩展BSGS)