kZjPBD.jpg

板子

题目描述

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

输入输出格式

输入格式:

每个测试文件中最多包含100组测试数据。

每组数据中,每行包含3个正整数a,p,b。

当a=p=b=0时,表示测试数据读入完全。

输出格式:

对于每组数据,输出一行。

如果无解,输出“No Solution”(不含引号),否则输出最小自然数解。

输入输出样例

输入样例#1: 复制
5 58 33
2 4 3
0 0 0
输出样例#1: 复制
9
No Solution

说明

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

 




xkt×xtdi=ydi(modpdi)
#include"bits/stdc++.h"
using namespace std;

typedef long long ll;
unordered_map <ll,ll> mp;

ll a,b,p;


ll bsgs(ll a,ll b,ll p)
{
   if(b==1)return 0; ll d; ll k=1; int cnt=0;

   while ((d=__gcd(a,p))^1)
   {
      if(b%d)return -1; // 不能整除,return ;
      b/=d; p/=d;cnt++;
      k=1ll*k*(a/d)%p;
      if(k==b)return cnt;   // a/d 的乘积等于现在的b,然后就能约掉,左边x取cnt,为0次幂

       // cout<<k<<" "<<a<<" "<<b<<" "<<p<<endl;
   }



   int m=sqrt(p)+1; ll kt=1;
   mp.clear();
   for (int i=0;i<m;i++)// 左边小步
   {
     mp[1LL*kt*b%p]=i;
     kt=kt*a%p; // 这里最后kt是a^ml

   }

   k=k*kt%p;

   for (int i=1;i<=m;i++)// 右边大步
   {
     if(mp.find(k)!=mp.end()) return i*m-mp[k]+cnt; // 查表
     k=k*kt%p;
   }

   return -1;

}

int main()
{
   while (cin>>a>>p>>b)
   {
       if(!a&&!b&&!p)break;
    //   cout<<123<<endl;
      ll ans=bsgs(a,b,p);
      if(ans!=-1)printf("%lld\n",ans);
      else puts("No Solution");
    //  cout<<123<<endl;

   }

}

 

 
 
 
 
posted @ 2019-02-20 08:28  Through_The_Night  阅读(138)  评论(0)    收藏  举报