BZOJ2480Spoj3105 Mod&BZOJ1467Pku3243 clever Y——EXBSGS

题目描述

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

输入

    每个测试文件中最多包含100组测试数据。
    每组数据中,每行包含3个正整数a,p,b。
    当a=p=b=0时,表示测试数据读入完全。

输出

    对于每组数据,输出一行。
    如果无解,输出“No Solution”(不含引号),否则输出最小自然数解。

样例输入

5 58 33
2 4 3
0 0 0

样例输出

9
No Solution

提示

  100%的数据,a,p,b≤1e9。

 

$EXBSGS$模板题,注意特判当$p=1$时输出$0$。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
map<int,int>mp;
ll a,b,p,ans;
inline ll gcd(ll x,ll y)
{
	return y==0?x:gcd(y,x%y);
}
inline void exgcd(ll &x,ll &y,ll a,ll b)
{
	if(!b)
	{
		x=1,y=0;
		return ;
	}
	exgcd(y,x,b,a%b);
	y-=(a/b)*x;
	return ;
}
inline ll quick(ll x,ll y,ll mod)
{
	ll res=1ll;
	while(y)
	{
		if(y&1)
		{
			res=res*x%mod;
		}
		y>>=1;
		x=x*x%mod;
	}
	return res;
}
inline ll BSGS(ll a,ll b,ll p,ll g)
{
	ll x,y;
	ll m=ceil(sqrt(p));
	exgcd(x,y,g,p);
	b=(b*x%p+p)%p;
	ll num=quick(a,m,p);
	exgcd(x,y,num,p);
	num=(x%p+p)%p;
	ll sum=1ll;
	mp.clear();
	for(int i=0;i<=m;i++)
	{
		if(!mp.count(sum))
		{
			mp[sum]=i;
		}
		sum*=a,sum%=p;
	}
	for(int i=0;i<=m;i++)
	{
		if(mp[b])
		{
			return mp[b]+i*m;
		}
		b*=num,b%=p;
	}
	return -1;
}
inline int EX_BSGS(int a,int b,int p)
{
	ll g=1ll;
	ll k=0;
	ll d,ans;
	if(b==1)
	{
		return 0;
	}
	while((d=gcd(a,p))!=1)
	{
		if(b%d)
		{
			return -1;
		}
		k++,b/=d,p/=d,g=g*(a/d)%p;
		if(g==b)
		{
			return k;
		}
	}
	ans=BSGS(a,b,p,g);
	return ans==-1?-1:ans+k;
}
int main()
{
	while(scanf("%d%d%d",&a,&p,&b))
	{
		if(!a&&!b&&!p)
		{
			break;
		}
		if(p==1)
		{
			printf("0\n");
			continue;
		}
		ans=EX_BSGS(a,b,p);
		printf(ans==-1?"No Solution\n":"%d\n",ans);
	}
}
posted @ 2019-03-30 15:22  The_Virtuoso  阅读(200)  评论(0编辑  收藏  举报