bzoj 1467: Pku3243 clever Y (扩展BSGS)

1467: Pku3243 clever Y

Time Limit: 4 Sec   Memory Limit: 64 MB
Submit: 211   Solved: 113
[ 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



题解:

bzoj 1467: Pku3243 clever Y (扩展BSGS)_第1张图片


注:BSGS和扩展欧几里德的应用条件都是是A,P互质,那么这道题出来下面写出的麻烦的方法,还可以直接求

A^x-k=B*inv(A^k)  (mod p')  ,inv(A^k) 用扩展欧几里德来求。

<span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define q 100003
using namespace std;
ll a,b,p,cnt,tot;
ll point[q<<1],v[q<<1],u[q<<1],next[q<<1];
void add(ll x,ll y)
{
	ll k=x%q; tot++;
	next[tot]=point[k];
	u[tot]=x;
	v[tot]=y;
	point[k]=tot;
}
ll find(int x)//hash
{
	ll k=x%q;
	for (ll i=point[k];i;i=next[i])
	 if (u[i]==x)
	  return v[i];
	return -1;
}
ll quickpow(ll num,ll x,ll m)//快速幂
{
	ll ans=1; ll base=num%m;
	while (x)
	{
		if (x&1) 
		 ans=ans*base%m;
		x>>=1;
		base=base*base%m;
	}
	return ans%m;
}
ll gcd(ll x,ll y)//最大公约数
{
	ll r;
	while (y)
	 {
	 	r=x%y; 
	 	x=y; 
	 	y=r;
	 }
	return x;
}
ll exbsgs(ll a,ll b,ll p)
{
	a%=p; b%=p;
	if (b==1) return 0;
	ll cnt=0,d=1,tmp=1;
	while((tmp=gcd(a,p))!=1)//不断除以a,p的最大公约数,直到a,p互质
	{
		if (b%tmp)  return -1;
	    b/=tmp; p/=tmp; cnt++;
	    d=d*(a/tmp)%p;//记录的是A^x-cnt的系数
	    if (b==d) return cnt;
	}
	ll m=ceil(sqrt(p)); ll ans=b;  ll sum=1;
	tot=0;
	memset(point,0,sizeof(point));
	memset(next,0,sizeof(next));
	tmp=quickpow(a,m,p);
	add(ans,0);
	for (ll i=1;i<=m;i++)
	 ans=ans*a%p,add(ans,i);
	for (ll i=1;i<=m+1;i++)
	 {
	 	d=d*tmp%p; 
		ll t=find(d); 
	 	if (t!=-1)
	 	 return i*m-t+cnt;
	 }
	return -1;
}
int main()
{
	freopen("input.txt","r",stdin);
	freopen("my.out","w",stdout);
	while (scanf("%I64d%I64d%I64d",&a,&p,&b))
	 {
	 	if (a==0&&b==0&&p==0) break;
	 	ll t=exbsgs(a,b,p);
	 	if (t!=-1)
	 	 printf("%I64d\n",t);
	 	else
	 	 printf("No Solution\n");
	 }
}</span>



你可能感兴趣的:(bzoj 1467: Pku3243 clever Y (扩展BSGS))