1. 程式人生 > >【BZOJ1467/2480】Pku3243 clever Y/Spoj3105 Mod EXBSGS

【BZOJ1467/2480】Pku3243 clever Y/Spoj3105 Mod EXBSGS

sof i++ long mod data -s for scrip input

【BZOJ1467/2480】Pku3243 clever Y/Spoj3105 Mod

Description

已知數a,p,b,求滿足a^x≡b(mod p)的最小自然數x。

Input

每個測試文件中最多包含100組測試數據。 每組數據中,每行包含3個正整數a,p,b。 當a=p=b=0時,表示測試數據讀入完全。

Output

對於每組數據,輸出一行。 如果無解,輸出“No Solution”(不含引號),否則輸出最小自然數解。

Sample Input

5 58 33
2 4 3
0 0 0

Sample Output

9
No Solution

HINT

100%的數據,a,p,b≤1e9。

題解:EXBSGS

因為A和C不互質,所以我們令A,B,C同時除以gcd(A,C),得到的C‘可能與A還不互質,所以我們再除上gcd(A,C‘),直到A,C互質。

此時得到方程$A^{x-k}*{A^k\over g_1*g_2...g_k}=B‘(mod C‘)$

將${A^k\over g_1*g_2...g_k}$除過去,然後套用BSGS即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <cmath>
using namespace std;
typedef long long ll;
map<int,int> mp;
int pm(int a,int b,int c)
{
	int ret=1;
	while(b)
	{
		if(b&1)	ret=(ll)ret*a%c;
		a=(ll)a*a%c,b>>=1;
	}
	return ret;
}
int gcd(int a,int b)
{
	return b?gcd(b,a%b):a;
}
int BSGS(int a,int b,int c,int d)
{
	int x,y,i;
	mp.clear();
	int M=ceil(sqrt(c));
	for(x=b,i=0;i<=M;i++,x=(ll)x*a%c)	mp[x]=i;
	for(y=d,x=pm(a,M,c),i=1;i<=M;i++)
	{
		y=(ll)y*x%c;
		int tmp=mp[y];
		if(tmp)	return (ll)i*M-tmp;
	}
	return -1;
}
void work(int a,int b,int c)
{
	int A=1,k=0;
	for(int i=0;(1<<i)<=c;i++)
	{
		if(pm(a,i,c)==b)
		{
			printf("%d\n",i);
			return ;
		}
	}
	while(1)
	{
		int g=gcd(a,c);
		if(g==1)	break;
		if(b%g!=0)
		{
			printf("No Solution\n");
			return ;
		}
		b/=g,c/=g,A=((ll)A*a/g)%c,k++;
	}
	int tmp=BSGS(a,b,c,A);
	if(tmp==-1)	printf("No Solution\n");
	else	printf("%d\n",tmp+k);
}
int main()
{
	int a,b,c;
	while(1)
	{
		scanf("%d%d%d",&a,&c,&b);
		if(!a&&!b&&!c)	return 0;
		if(!a&&!b)	printf("1\n");
		else	a%=c,b%=c,work(a,b,c);
	}
}

【BZOJ1467/2480】Pku3243 clever Y/Spoj3105 Mod EXBSGS