http://www.lydsy.com/JudgeOnline/problem.php?id=4869
终于A了。。。参考了下dalao的代码。。。
拓展欧几里得定理,改了几次就不变了,但是用的时候要在快速幂里判是不是要用。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 100010; int n, m, cnt; ll p, c; ll phi[N], table[N]; namespace seg // n^x = n^(x % phi[x] + phi[x]) {struct data {ll ans, mn;} tree[N << 2];inline ll getphi(ll x){ll ret = x, lim = x;for(ll i = 2; i * i <= lim; ++i) if(x % i == 0) {ret = ret * (i - 1) / i;while(x % i == 0) x /= i;} // printf("ret=%d\n", ret);if(x > 1) ret = ret * (x - 1) / x;return ret;}inline ll power(ll x, ll t, ll p, bool &flag){bool big = false;ll ret = 1; for(; t; t >>= 1) {if(t & 1) {ret = ret * x ;flag |= big | (ret >= p); ret %= p;}x = x * x; if(x >= p) big = true, x %= p; }return ret; }ll calc(ll x, int t){if(x >= phi[t]) x = x % phi[t] + phi[t];for(int i = t - 1; i >= 0; --i) {bool flag = false;x = power(c, x, phi[i], flag);if(flag) x += phi[i];}return x % phi[0];}inline void build(int l, int r, int x){if(l == r) { tree[x].ans = table[l]; return; }int mid = (l + r) >> 1;build(l, mid, x << 1); build(mid + 1, r, x << 1 | 1);tree[x].ans = (tree[x << 1].ans + tree[x << 1 | 1].ans) % phi[0];} inline void update(int l, int r, int x, int a, int b){ //如果这次的幂和上次一样就不变了 if(tree[x].mn >= cnt) return;if(l > b || r < a) return;if(l == r){++tree[x].mn;tree[x].ans = calc(table[l], tree[x].mn);return;}int mid = (l + r) >> 1;update(l, mid, x << 1, a, b); update(mid + 1, r, x << 1 | 1, a, b);tree[x].mn = min(tree[x << 1].mn, tree[x << 1 | 1].mn);tree[x].ans = (tree[x << 1].ans + tree[x << 1 | 1].ans) % phi[0]; }inline ll query(int l, int r, int x, int a, int b){if(l > b || r < a) return 0;if(l >= a && r <= b) return tree[x].ans % phi[0];int mid = (l + r) >> 1, ret = 0;ret = (ret + query(l, mid, x << 1, a, b)) % phi[0];ret = (ret + query(mid + 1, r, x << 1 | 1, a, b)) % phi[0];return ret; } } using namespace seg; int main() {scanf("%d%d%lld%lld", &n, &m, &p, &c);phi[0] = p;ll P = p;while(P != 1) phi[++cnt] = P = getphi(P);phi[++cnt] = 1; for(int i = 1; i <= n; ++i) scanf("%lld", &table[i]);build(1, n, 1); while(m--){int opt, l, r; scanf("%d", &opt);if(opt == 0){scanf("%d%d", &l, &r); update(1, n, 1, l, r);}if(opt == 1) {scanf("%d%d", &l, &r);printf("%lld\n", query(1, n, 1, l, r));}}return 0; }