标签:
即求区间的乘积的欧拉函数模一个数
预处理前60个素数和逆元,用线段树维护区间乘机和每个素数出现的次数(我用了bitset嗯嗯嗯)
于是可以O(sqrt(n))求出欧拉函数
1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26 27 27 28 28 29 29 30 30 31 31 32 32 33 33 34 34 35 35 36 36 37 37 38 38 39 39 40 40 41 41 42 42 43 43 44 44 45 45 46 46 47 47 48 48 49 49 50 50 51 51 52 52 53 53 54 54 55 55 56 56 57 57 58 58 59 59 60 60 61 61 62 62 63 63 64 64 65 65 66 66 67 67 68 68 69 69 70 70 71 71 72 72 73 73 74 74 75 75 76 76 77 77 78 78 79 79 80 80 81 81 82 82 83 83 84 84 85 85 86 86 87 87 88 88 89 89 90 90 91 91 92 92 93 93 94 94 95 95 96 96 97 97 98 98 99 99 100 100 101 101 102 102 103 103 104 104 105 105 106 106 107 107 108 108 109 109 110 110 111 111 112 112 113 113 114 114 115 115 116 116 117 117 118 118 119 119 120 120 121 121 122 122 123 123 124 /************************************************************** 125 Problem: 3813 126 User: rausen 127 Language: C++ 128 Result: Accepted 129 Time:1644 ms 130 Memory:8624 kb 131 ****************************************************************/ 132 133 #include <cstdio> 134 #include <bitset> 135 136 using namespace std; 137 typedef long long ll; 138 const int mod = 19961993; 139 const int N = 1e5 + 5; 140 141 struct segment{ 142 ll v; 143 bitset <65> ap; 144 } seg[N << 2]; 145 146 int n, m; 147 ll v; 148 bitset <65> ap; 149 int pr[65], tot; 150 ll inv[65]; 151 bool vis[305]; 152 153 inline int read() { 154 int x = 0; 155 char ch = getchar(); 156 while (ch < ‘0‘ || ‘9‘ < ch) 157 ch = getchar(); 158 while (‘0‘ <= ch && ch <= ‘9‘) { 159 x = x * 10 + ch - ‘0‘; 160 ch = getchar(); 161 } 162 return x; 163 } 164 165 inline ll pow(ll x, int y) { 166 ll res = 1; 167 while (y) { 168 if (y & 1) res = res * x % mod; 169 x = x * x % mod; 170 y >>= 1; 171 } 172 return res; 173 } 174 175 void pre_work() { 176 int i, j; 177 for (i = 2; tot <= 60; ++i) 178 if (!vis[i]) { 179 pr[++tot] = i; 180 for (j = i; j <= 300; j += i) vis[j] = 1; 181 } 182 for (i = 1; i <= 60; ++i) 183 inv[i] = 1ll * pow(pr[i], mod - 2) * (pr[i] - 1) % mod; 184 } 185 186 #define Ls (p << 1) 187 #define Rs (p << 1 | 1) 188 #define mid (l + r >> 1) 189 inline void update(int p) { 190 seg[p].v = seg[Ls].v * seg[Rs].v % mod; 191 seg[p].ap = seg[Ls].ap | seg[Rs].ap; 192 } 193 194 void seg_build(int p, int l, int r) { 195 if (l == r) { 196 seg[p].v = 3, seg[p].ap[2] = 1; 197 return; 198 } 199 seg_build(Ls, l, mid), seg_build(Rs, mid + 1, r); 200 update(p); 201 } 202 203 void seg_modify(int p, int l, int r, int pos, int v) { 204 if (l == r) { 205 int i; 206 seg[p].v = v, seg[p].ap.reset(); 207 for (i = 1; i <= 60; ++i) 208 if (v % pr[i] == 0) seg[p].ap[i] = 1; 209 return; 210 } 211 if (pos <= mid) seg_modify(Ls, l, mid, pos, v); 212 else seg_modify(Rs, mid + 1, r, pos, v); 213 update(p); 214 } 215 216 void seg_query(int p, int l, int r, int L, int R) { 217 if (L <= l && r <= R) { 218 v = v * seg[p].v % mod, ap |= seg[p].ap; 219 return; 220 } 221 if (L <= mid) seg_query(Ls, l, mid, L, R); 222 if (mid < R) seg_query(Rs, mid + 1, r, L, R); 223 } 224 #undef mid 225 #undef Ls 226 #undef Rs 227 228 int main() { 229 int oper, x, y, i; 230 pre_work(); 231 n = 1e5; 232 seg_build(1, 1, n); 233 m = read(); 234 while (m--) { 235 oper = read(), x = read(), y = read(); 236 if (oper) seg_modify(1, 1, n, x, y); 237 else { 238 v = 1, ap.reset(); 239 seg_query(1, 1, n, x, y); 240 for (i = 1; i <= 60; ++i) 241 if (ap[i]) v = v * inv[i] % mod; 242 printf("%lld\n", v); 243 } 244 } 245 return 0; 246 }
标签:
原文地址:http://www.cnblogs.com/rausen/p/4333260.html