重排DL

题解:

https://www.luogu.org/problemnew/show/T51442

从这题上还是学到不少东西。。

以前并没有写过ex-bsgs

正好拿这个复习中国剩余定理和bsgs了(我觉得noip肯定不考这东西)

看过一篇博客说把乘法变除法避免逆元操作

然后我就这么写了 对拍一下会发现是错的

为什么呢

$ a^b=k*a^c\ (\ mod\ m) $ 并不能推导出

$ a^{b-c}=k \ (\ mod\ m) $

只有当m和a互素才成立

所以还是得ex-bsgs

至于ex-bsgs详见xxy https://www.cnblogs.com/TheRoadToTheGold/p/8478697.html

写的很详细了

另外这题还卡常数啊

传统的快速乘并不行

有一种叫做O(1)快速乘的东西

LL modmul(LL A,LL B,LL mod)
{
    return (A*B-(LL)((long double)A*B/mod)*mod+mod)%mod;
}

于是我决定明天重新写一下这题。。

代码:

 

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;++i)
#define dep(i,t,h) for (int i=t;i>=h;--i)
#define ll long long
map<ll,ll> M;
ll n,m,b;
IL ll cf(ll x,ll y)
{
  ll t=(x*y-(ll)((long double)x*y/m)*m);
  if (t<0) return t+m; else return t;
}
ll gcd(ll x,ll y)
{
  if (!y) return(x);
  return gcd(y,x%y);
}
ll ksm(ll x,ll y)
{
  if (!y) return(1);
  if (y==1) return(x);
  ll ans=ksm(x,y/2);
  ans=cf(ans,ans);
  if (y%2==1) ans=cf(ans,x);
  return ans;
}
int main()
{
  ios::sync_with_stdio(false);
  cin>>n>>m>>b;
  b=((b-n)%m+m)%m;
  ll a1=((cf(2,n)-1)%m+m)%m;
  ll tmp=1;
  ll ans=0;
  while (1)
  {
    ll d=gcd(a1,m);
    if (d==1) break;
    if (b%d)
    {
      cout<<"INF"<<endl;
      exit(0);
    }
    b/=d; m/=d; ans++;
    tmp=cf(tmp,a1/d);
    if (tmp==b)
    {
      cout<<ans<<endl;
      exit(0);
    }
  }
  ll k=sqrt(m);
  if (k*k<m) k++;
  ll now=b;
  rep(i,1,k)
  {
    now=cf(now,a1);
    M[now]=i;
  }
  now=tmp;
  ll a2=ksm(a1,k);
  rep(i,1,k)
  {
    now=cf(now,a2);
    if (M[now])
    {
      cout<<i*k-M[now]+ans<<endl;
      exit(0);
    }
  }
  cout<<"INF"<<endl;
  return 0;
}

 

posted @ 2018-10-29 23:08  尹吴潇  阅读(141)  评论(0编辑  收藏  举报