Time Limit: 5000MS Memory Limit: 65536K
Description
Little Y finds there is a very interesting formula in mathematics:
X^Y mod Z = K
Given X, Y, Z, we all know how to figure out K fast. However, given X, Z, K, could you figure out Y fast?
Input
Input data consists of no more than 20 test cases. For each test case,there would be only one line containing 3 integers X, Z, K (0 ≤ X, Z,K ≤ 109). Input file ends with 3 zeros separated by spaces.
Output
For each test case output one line. Write “No Solution” (without quotes) if you cannot find a feasible Y (0 ≤ Y < Z). Otherwise output the minimum Y you find.
Sample Input
5 58 33
2 4 3
0 0 0
Sample Output
9
No Solution
Solution
扩展BSGS模板题,留作纪念,代码是我凭想象写的,不知有没有bug……
Code
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const ll mod=76543;
ll k,x,y,z,top,hs[mod],id[mod],Last[mod],Next[mod];
ll GCD(ll a,ll b)
{
return !b?a:GCD(b,a%b);
}
void Insert(ll a,ll b)
{
ll c=a%mod;
hs[++top]=a,id[top]=b,Next[top]=Last[c],Last[c]=top;
}
ll Find(ll a)
{
ll b=a%mod;
for(ll i=Last[b];i;i=Next[i])
if(hs[i]==a) return id[i];
return -1;
}
ll Extended_BSGS(ll a,ll b,ll c)
{
ll d=1,r,cnt=0;
for(ll i=0,j=1;i<=ceil(log2(c));i++,j=j*a%c)
if(j%c==b) return i;
while((r=GCD(a,c))!=1)
{
if(b%r!=0) return -1;
b/=r,c/=r,d=d*a/r%c,cnt++;
}
ll m=sqrt(c),j=1,t=1,l;
for(ll i=0;i<m;i++,j=j*a%c) Insert(j*b%c,i);
for(ll i=m;i<=c;i+=m)
if(~(l=Find(d*(t=t*j%c)%c))) return i-l+cnt;
return -1;
}
int main()
{
while(~scanf("%lld%lld%lld",&x,&z,&k)&&(x||z||k))
{
top=0,k%=z;
memset(Last,0,sizeof(Last));
y=Extended_BSGS(x,k,z);
if(~y) printf("%lld\n",y);
else puts("No Solution");
}
return 0;
}