Codeforces 919E Congruence Equation(循环节+数论)

Link

题意

给$n, m, p, x$,求有多少个$n(1\leq n \leq x)$使得$n·a^{n}=b(\textrm{mod}\;p)$成立

思路

考虑一下左边的循环节长度,由于$n%p$的循环节长度为$p$,$a^{n}%p$的循环节长度为$p-1$(根据费马小定理$a^{0}=a^{p-1}=1(\textrm{mod}\;p)$),所以(大胆猜测)左边的循环节长度就是$p*(p-1)$。接下来,设$n=k*(p-1)+i$,有原式:

$n·a^{n}=b(\textrm{mod}\;p)$

$n=b*a^{-n}(\textrm{mod}\;p)$

$k*(p-1)+i=b*a^{-k*(p-1)-i}(\textrm{mod}\;p)$

$-k+i=b*a^{-i}(\textrm{mod}\;p)$

$k=i-b*a^{-i}(\textrm{mod}\;p)$

由于$a^{i}(\textrm{mod}\;p)$的值至多$p-1$个,所以枚举$i$即可算出$k$,即可算出$n=k*(p-1)+i$此为当前$i$下$n$的最小值,然后算一下加了循环节长度之后有多少满足的$n$即可。

Code

#include <bits/stdc++.h>
#define DBG(x) cerr << #x << " = " << x << endl

using namespace std;
typedef long long ll;

const int N = 1e6 + 5;

ll a, b, p, x, ans, pw[N];

ll fpow(ll a, ll b, ll mod) {
    ll res = 1; a %= mod;
    for(; b; b >>= 1, a = a * a % mod) if(b & 1) res = res * a % mod;
    return res;
}

int main() {
    scanf("%lld%lld%lld%lld", &a, &b, &p, &x);
    ll G = p * (p - 1);
    for(int i = 1; i <= p - 1; i++) {
        pw[i] = i == 1 ? a : pw[i - 1] * a % p;
        ll k = ((i - b * fpow(pw[i], p - 2, p) % p) % p + p) % p;
        if(x >= k * (p - 1) + i) ans += (x - k * (p - 1) - i) / G + 1;
    }
    printf("%lld\n", ans);
}
posted @ 2019-11-07 17:07  WstOne  阅读(204)  评论(0编辑  收藏  举报