【题目】
题目描述:
已知数 ,求满足 的最小自然数 。
输入格式:
每个测试文件中最多包含 组测试数据。
每组数据中,每行包含 个正整数 。
当 时,表示测试数据读入完全。
输出格式:
对于每组数据,输出一行。
如果无解,输出 “No Solution”(不含引号),否则输出最小自然数解。
样例数据:
输入
5 58 33
2 4 3
0 0 0
输出
9
No Solution
说明:
对于 的数据, 。
【分析】
这是一道 exBSGS 的模板题。
具体的做法就看我的另一篇博客 BSGS。
【代码】
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<tr1/unordered_map>
#define ll long long
using namespace std;
using namespace tr1;
unordered_map<int,int>Hash;
int Power(ll a,ll b,int p)
{
ll ans=1;
for(;b;b>>=1,a=a*a%p)if(b&1)ans=ans*a%p;
return ans;
}
void exBSGS(int a,int b,int p)
{
int i,num=0,k=1;
int t=ceil(sqrt(p));
while(1)
{
int Gcd=__gcd(a,p);
if(Gcd==1) break;
if(b%Gcd){puts("No Solution");return;}
b/=Gcd,p/=Gcd,num++,k=(ll)k*(a/Gcd)%p;
if(k==b){printf("%d\n",num);return;}
}
int now=b;
Hash.clear();
for(i=0;i<t;++i)
Hash[now]=i,now=(ll)now*a%p;
now=k,a=Power(a,t,p);
for(i=0;i<=t;++i)
{
int j=(Hash.find(now)==Hash.end())?-1:Hash[now];
if(j>=0&&i*t-j>=0) {printf("%d\n",i*t-j+num);return;}
now=(ll)now*a%p;
}
puts("No Solution");
}
int main()
{
int a,p,b;
while(scanf("%d%d%d",&a,&p,&b))
{
if(!a&&!b&&!p) break;
exBSGS(a,b,p);
}
return 0;
}