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 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.
5 58 33 2 4 3 0 0 0
Sample Output
9 No Solution
Solution
扩展BSGS模板题,留作纪念,代码是我凭想象写的,不知有没有bug……
Code
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;
}