Codeforces Round #460 E. Congruence Equation

Description

题面
\(n*a^n≡b (\mod P),1<=n<=x\)

Solution

\(n=(P-1)*i+j\)
\([(P-1)*i+j]*a^{[(P-1)*i+j]} ≡b (\mod P)\)
由费马小定理
\([(P-1)*i+j]*a^j ≡b (\mod P)\)
\(i ≡j-\frac{b}{a^{j}} (\mod P)\)
然后就可以枚举\(j\),算\(i\)的取值种数了
利用 \(i\) 的限制:\(i*(P-1)+j<=x\),可以算出取值范围是一个前缀,再在前缀中算出满足同余要求的即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b,P,x;
ll qm(ll x,ll k){
  ll sum=1;
  while(k){
    if(k&1)sum=1ll*sum*x%P;
    x=x*x%P;k>>=1;
  }
  return sum;
}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  cin>>a>>b>>P>>x;
  ll inv=qm(a,P-2),aj=b,ans=0;
  for(int j=0;j<P-1;j++){
    ll i=(j-aj)%P;
    if(i<0)i+=P;
    if(x>=j && (x-j)/(P-1)>=i){
      ll t=(x-j)/(P-1);
      ans+=t/P+(t%P>=i);
    }
    aj=aj*inv%P;
  }
  if(b==0)ans--;
  cout<<ans<<endl;
  return 0;
}

posted @ 2018-02-02 19:21  PIPIBoss  阅读(186)  评论(0编辑  收藏  举报