即求区间的乘积的欧拉函数模一个数
预处理前60个素数和逆元,用线段树维护区间乘机和每个素数出现的次数(我用了bitset嗯嗯嗯)
于是可以O(sqrt(n))求出欧拉函数
1 /************************************************************** 2 Problem: 3813 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:1644 ms 7 Memory:8624 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <bitset> 12 13 using namespace std; 14 typedef long long ll; 15 const int mod = 19961993; 16 const int N = 1e5 + 5; 17 18 struct segment{ 19 ll v; 20 bitset <65> ap; 21 } seg[N << 2]; 22 23 int n, m; 24 ll v; 25 bitset <65> ap; 26 int pr[65], tot; 27 ll inv[65]; 28 bool vis[305]; 29 30 inline int read() { 31 int x = 0; 32 char ch = getchar(); 33 while (ch < '0' || '9' < ch) 34 ch = getchar(); 35 while ('0' <= ch && ch <= '9') { 36 x = x * 10 + ch - '0'; 37 ch = getchar(); 38 } 39 return x; 40 } 41 42 inline ll pow(ll x, int y) { 43 ll res = 1; 44 while (y) { 45 if (y & 1) res = res * x % mod; 46 x = x * x % mod; 47 y >>= 1; 48 } 49 return res; 50 } 51 52 void pre_work() { 53 int i, j; 54 for (i = 2; tot <= 60; ++i) 55 if (!vis[i]) { 56 pr[++tot] = i; 57 for (j = i; j <= 300; j += i) vis[j] = 1; 58 } 59 for (i = 1; i <= 60; ++i) 60 inv[i] = 1ll * pow(pr[i], mod - 2) * (pr[i] - 1) % mod; 61 } 62 63 #define Ls (p << 1) 64 #define Rs (p << 1 | 1) 65 #define mid (l + r >> 1) 66 inline void update(int p) { 67 seg[p].v = seg[Ls].v * seg[Rs].v % mod; 68 seg[p].ap = seg[Ls].ap | seg[Rs].ap; 69 } 70 71 void seg_build(int p, int l, int r) { 72 if (l == r) { 73 seg[p].v = 3, seg[p].ap[2] = 1; 74 return; 75 } 76 seg_build(Ls, l, mid), seg_build(Rs, mid + 1, r); 77 update(p); 78 } 79 80 void seg_modify(int p, int l, int r, int pos, int v) { 81 if (l == r) { 82 int i; 83 seg[p].v = v, seg[p].ap.reset(); 84 for (i = 1; i <= 60; ++i) 85 if (v % pr[i] == 0) seg[p].ap[i] = 1; 86 return; 87 } 88 if (pos <= mid) seg_modify(Ls, l, mid, pos, v); 89 else seg_modify(Rs, mid + 1, r, pos, v); 90 update(p); 91 } 92 93 void seg_query(int p, int l, int r, int L, int R) { 94 if (L <= l && r <= R) { 95 v = v * seg[p].v % mod, ap |= seg[p].ap; 96 return; 97 } 98 if (L <= mid) seg_query(Ls, l, mid, L, R); 99 if (mid < R) seg_query(Rs, mid + 1, r, L, R); 100 } 101 #undef mid 102 #undef Ls 103 #undef Rs 104 105 int main() { 106 int oper, x, y, i; 107 pre_work(); 108 n = 1e5; 109 seg_build(1, 1, n); 110 m = read(); 111 while (m--) { 112 oper = read(), x = read(), y = read(); 113 if (oper) seg_modify(1, 1, n, x, y); 114 else { 115 v = 1, ap.reset(); 116 seg_query(1, 1, n, x, y); 117 for (i = 1; i <= 60; ++i) 118 if (ap[i]) v = v * inv[i] % mod; 119 printf("%lld\n", v); 120 } 121 } 122 return 0; 123 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen