【bzoj 1467】Pku3243 clever Y(扩展BSGS)
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;
}
既然无能更改,又何必枉自寻烦忧