CodeForces - 919E Congruence Equation//同余式推理

题目:
CodeForces - 919E Congruence Equation//同余式推理_第1张图片
思路:
n ∗ a n = b   ( m o d   p ) n*a^n=b\ (mod\ p) nan=b (mod p)
n = i + ( p − 1 ) ∗ k   ( m o d   p ) n=i+(p-1)*k\ (mod\ p) n=i+(p1)k (mod p)
得到 k = ( b / a i − i ) / ( p − 1 )   ( m o d   p ) / / k=(b/a^i-i)/(p-1)\ (mod\ p) // k=(b/aii)/(p1) (mod p)//费马小定理
然后枚举 i ∈ [ 0 , p − 2 ] i∈[0,p-2] i[0,p2],对于每一个 i i i 可以得到最小的正整数 k k k 满足同余式,那么 k + p ∗ j k+p*j k+pj 都是满足同余的,此时只需要保证 i + ( p − 1 ) ∗ ( k + p ∗ j ) < = x i+(p-1)*(k+p*j)<=x i+(p1)(k+pj)<=x n < = x n<=x n<=x 即可完美的不重不漏统计答案。
同余还是秒啊啊

/*   Author : Rshs   */
#include
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
LL infa[MXN],inv[MXN],fac[MXN];
void CCinit(int n,LL p){
    fac[0]=1;
    infa[1]=inv[1]=fac[1]=1;
    for(LL i=2;i<=n;i++) fac[i]=fac[i-1]*i%p; //阶乘
    for(LL i=2;i<=n;i++) inv[i]=(p-p/i)*inv[p%i]%p; //逆元
    for(LL i=2;i<=n;i++) infa[i]=infa[i-1]*inv[i]%p; //逆元前缀乘
}

int main(){
    LL a,b,p,x;cin>>a>>b>>p>>x;
    CCinit(1e6+5,p);
    LL ans=0;
    LL ai=1;
    for(LL i=0;i<p-1;i++,ai=ai*a%p){
        LL k=(b*inv[ai]%p-i)*inv[p-1]%p;
        k=(k+p)%p; //最小的k,之后k不停+p,要保证n=+k*(p-1)<=x
        LL yu=x-k*(p-1)-i;
        if(yu<0)continue;
        ans++;
        ans+=(yu/(p*(p-1)));

    }
    cout<<ans<<'\n';
    return 0;
}

你可能感兴趣的:(CodeForces - 919E Congruence Equation//同余式推理)