【NOI2018模拟4.7】power(扩展欧拉定理)

Description:

【NOI2018模拟4.7】power(扩展欧拉定理)_第1张图片

题解:

必要定理:

扩展欧拉定理:

a,b 有 正 整 数 a , b
ab=ab(mod p)(b<ϕ(p)) a b = a b ( m o d   p ) ( b < ϕ ( p ) )
ab=ab mod ϕ(p)+ϕ(p)(mod p)(b>=ϕ(p)) a b = a b   m o d   ϕ ( p ) + ϕ ( p ) ( m o d   p ) ( b >= ϕ ( p ) )

phi一直迭代下去log次就变成1了,这个易证。

所以这题是个结论题。

Code:

#include
#include
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;

const int N = 100000;

int bz[N + 5], p[N];

void Built() {
    fo(i, 2, N) {
        if(!bz[i]) p[++ p[0]] = i;
        fo(j, 1, p[0]) {
            if(i * p[j] > N) break;
            bz[i * p[j]] = 1;
            if(!(i % p[j])) break;
        }
    }
}

int qphi(int x) {
    int s = x;
    for(int i = 1; p[i] * p[i] <= x; i ++)
        if(x % p[i] == 0) {
            s = s / p[i] * (p[i] - 1);
            while(x % p[i] == 0) x /= p[i];
        }
    if(x > 1) s = s / x * (x - 1);
    return s;
}

int n, m, m0, a[N + 5], Q, l, r, d[N];

int dg(int l, int r, int u) {
    if(l > r) return 1;
    if(u > d[0]) return 1;
    if(l == r) return a[l] >= d[u] ? (a[l] % d[u] + d[u]) : a[l];
    int y = dg(l + 1, r, u + 1);
    int b1 = 0, b2 = 0; ll s = 1, x = a[l], mo = d[u];
    while(y) {
        if(y & 1) {
            b1 |= (s * x >= mo) | b2;
            s = s * x % mo;
        }
        y /= 2;
        b2 |= x * x >= mo;
        x = x * x % mo;
    }
    return (b1) ? s + mo : s;
}

int main() {
    freopen("power.in", "r", stdin);
    freopen("power.out", "w", stdout);
    Built();
    scanf("%d %d", &n, &m); m0 = m;
    while(m > 1) {
        m = qphi(m);
        d[++ d[0]] = m;
    }
    fo(i, 1, n) scanf("%d", &a[i]);
    for(scanf("%d", &Q); Q; Q --) {
        scanf("%d %d", &l, &r);
        ll y = dg(l + 1, r, 1);
        ll x = a[l], s = 1, mo = m0;
        while(y) {
            if(y & 1) s = s * x % mo;
            y /= 2; x = x * x % mo;
        }
        printf("%lld\n", s);
    }
}

你可能感兴趣的:(数论杂集)