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;
}

原文地址:https://www.cnblogs.com/Yuzao/p/8406811.html