bzoj2242,洛谷2485----SDOI2011计算器(exgcd,qsm,bsgs模板)

就是一道模板题!

这里再强调一下

BSGS

考虑方程\(a^x = b \pmod p\)

已知a,b,p\((2 \le p\le 10^9)\),其中p为质数,求x的最小正整数解

解法:

注意到如果有解,那么一定满足\(0<x<p\)

\(t=\lfloor \sqrt p \rfloor\)

那么一定有

\((a^t)^c=ba^d \pmod p\)

此时\(x=ct-d(0 \le d <t)\)

因为$$\frac{a{ct}}{ad} = b \pmod p$$

那么我们预处理一个\(a^d\),因为d的取值只有t个,所以可以先预处理,然后暴力枚举左边,看看有没有合法的解

不多说了
直接上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#include<map>

using namespace std;

inline ll read()
{
  ll x=0,f=1;char ch=getchar();
  while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
  while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}

ll n,m;
ll mod;
map<ll,ll> mp;

ll qsm(ll i,ll j)
{
    ll ans=1;
    while (j)
    {
        if (j&1) ans=ans*i%mod;
        i=i*i%mod;
        j>>=1;
    }
    return ans;
}

ll exgcd(ll &x,ll &y,ll a,ll b)
{
    if (b==0)
    {
        x=1;
        y=0;
        return a;
    }
    ll cnt=exgcd(x,y,b,a%b);
    ll tmp =x;
    x=y;
    y=tmp-a/b*y;
    return cnt;
}

ll bsgs(ll a,ll b)
{	
    mp.clear(); 
    if (a%mod==0 && b==0) return 0;
    if (a%mod==0 && b!=0) return -1;
    //if (a==1 && b!=1) return -1;
    //if (a==1 && b==1) return 0;
    //==0) return -1;
    ll t = ceil(sqrt(mod));
    for (ll i=0;i<=t;i++) 
    {
        ll tmp = qsm(a,i)*b%mod;
        if (!mp[tmp]) mp[tmp]=i;
    }
    for (ll c=1;c<=t;c++)
    {
    	ll cnt = qsm(a,c*t)%mod;
    	if (mp[cnt])
    	{
    		//cout<<c*t<<endl;
    		return c*t-mp[cnt];
        }
    }
    return -1;
}

int main()
{
  scanf("%d%d",&n,&m);
  if (m==1)
  {
  	 for (int i=1;i<=n;i++)
  	 {
  	 ll x,y;
  	 x=read(),y=read(),mod=read();
  	 printf("%lld\n",qsm(x,y));
     }
  }
  
  if (m==2)
  {
  	for (int i=1;i<=n;i++)
      {
      	ll a,b,c;
      	ll x=0,y=0;
      	a=read(),c=read(),b=read();
      	ll gcd=exgcd(x,y,a,b);
      	if (c%gcd!=0)
      	{
      		printf("Orz, I cannot find x!\n");
      		continue;
        }
        ll tmp = b/gcd;
      	x=x*c/gcd%tmp;
      	x=(x%tmp+tmp)%tmp;
      	printf("%lld\n",x);
       } 
  }
  //return 0;
  if (m==3)
  {
  	 for (int i=1;i<=n;i++)
  	 {
  	 	ll a,b;
  	 	a=read(),b=read(),mod=read();
  	 	ll tmp = bsgs(a,b);
  	 	if (tmp==-1)
  	 	  printf("Orz, I cannot find x!\n");
  	 	else
  	 	  printf("%lld\n",tmp);
       }
  }
  return 0;
}

posted @ 2018-12-22 13:39  y_immortal  阅读(119)  评论(0编辑  收藏  举报