即求区间的乘积的欧拉函数模一个数

预处理前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 }
View Code

 

posted on 2015-03-12 18:33  Xs酱~  阅读(342)  评论(0编辑  收藏  举报