【EX_BSGS】BZOJ1467 Pku3243 clever Y
1467: Pku3243 clever Y
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 425 Solved: 238
[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
2 4 3
0 0 0
Sample Output
9
No Solution
题解
EX_BSGS模板题
思路懒得写了
代码
//by 减维 #include<set> #include<map> #include<queue> #include<ctime> #include<cmath> #include<bitset> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define il inline #define rg register #define db double #define mpr make_pair #define maxn #define inf (1<<30) #define eps 1e-8 #define pi 3.1415926535897932384626L using namespace std; inline int read() { int ret=0;bool fla=0;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-'){fla=1;ch=getchar();} while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();} return fla?-ret:ret; } ll x,y,p; map<ll,ll> mp; ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);} ll ksm(ll x,ll y,ll p) { ll ret=1;x%=p; for(;y;y>>=1,x=x*x%p) if(y&1) ret=ret*x%p; return ret; } ll exbsgs(ll x,ll y,ll p) { x%=p;y%=p; if(!x&&!y) return 1; if(y==1) return 0; if(!x) return -1; ll t,d=1,k=0; while((t=gcd(p,x))!=1) { if(y%t) return -1; y/=t,p/=t,d=d*x/t%p,k++; if(d==y) return k; } mp.clear(); ll m=sqrt(p+0.5); ll o=y; for(int i=0;i<=m;++i,o=o*x%p) if(!mp.count(o)) mp[o]=i; ll tmp=ksm(x,m,p); for(int i=1;i<=m;++i) { d=d*tmp%p; if(mp.count(d)) return ((i*m-mp[d])%p+k+p)%p; } return -1; } int main() { while(1) { scanf("%lld%lld%lld",&x,&p,&y); if(!x&&!y&&!p) break; ll ans=exbsgs(x,y,p); if(ans==-1) printf("No Solution\n"); else printf("%lld\n",ans); } return 0; }