码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5152 A Strange Problem线段树+欧拉函数

时间:2014-12-28 11:33:08      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:

*****************************************BC题解**********************************************************************
1003 A Strange Problem 对于操作二,利用公式 当x >= Phi(C), A^x = A ^ (x%Phi(C) + Phi(C)) (mod C) 对于2333333这个模数来说,求18次欧拉函数后就变成了1,所以只需要保存19层第三次操作的加数即可,然后就直接是线段树区间更新和询问操作了。 Ps:很多人把题目想简单了,操作二不能直接简单的更新,不满足2^(2^x) mod P = 2^( 2^x mod P) mod P。
*********************************************************************************************************************

辅助公式:

a^b=a^(b%phi(c)+phi(c))(mod c);

phi(c)为1~c中,与c互质的数的个数。

((a^b)^c)=a^(b^c)

a^(b^c)=a^(b^c%phi(c)+phi(c)) (mod c);

b^c%phi(c)=b^(c%phi(phi(c))+phi(phi(c)));

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <vector>
  4 #include <algorithm>
  5 #include <ctime>
  6 #include <iostream>
  7 using namespace std;
  8 
  9 typedef __int64 ll;
 10 const int MOD = 2333333;
 11 const int N = 50000+5;
 12 
 13 int mo[20] = {2333333,2196720,580608,165888,55296,18432,
 14 6144,2048,1024,512,256,128,64,32,16,8,4,2,1};
 15 int pow2[33];
 16 
 17 vector<ll> vt[N];
 18 struct Segtree {
 19 #define lson rt<<1, l, mid
 20 #define rson rt<<1|1, mid+1, r
 21     ll mark[N<<2];
 22     int length[N<<2], sum[N<<2];
 23     void build(int rt, int l, int r) {
 24         mark[rt] = 0;
 25         length[rt] = r-l+1;
 26         if(l == r) {
 27             vt[l].clear();
 28             int x;
 29             scanf("%d", &x);
 30             vt[l].push_back(x);
 31             sum[rt] = x%MOD;
 32             return ;
 33         }
 34         int mid = l+r>>1;
 35         build(lson); build(rson);
 36         up(rt);
 37     }
 38 
 39     inline void Add(int &x, int y) {
 40         x += y;
 41         if(x >= MOD)    x -= MOD;
 42     }
 43 
 44     void up(int rt) {
 45         sum[rt] = sum[rt<<1] + sum[rt<<1|1];
 46         Add(sum[rt], 0);
 47     }
 48 
 49     void down(int rt) {
 50         if(mark[rt]) {
 51             mark[rt<<1] += mark[rt];
 52             mark[rt<<1|1] += mark[rt];
 53             Add(sum[rt<<1], 1LL*length[rt<<1]*mark[rt]%MOD);
 54             Add(sum[rt<<1|1], 1LL*length[rt<<1|1]*mark[rt]%MOD);
 55             mark[rt] = 0;
 56         }
 57     }
 58 
 59     void update(int rt, int l, int r, int L, int R, int v) {
 60         if(L <= l && R >= r) {
 61             mark[rt] += v;
 62             Add(sum[rt], 1LL*length[rt]*v%MOD);
 63             return ;
 64         }
 65         down(rt);
 66         int mid = l+r>>1;
 67         if(L <= mid)    update(lson, L, R, v);
 68         if(R > mid) update(rson, L, R, v);
 69         up(rt);
 70     }
 71 
 72     int pow_mod(int x, int n, int mod) {
 73         int ret = 1%mod;
 74         while(n) {
 75             if(n&1) ret = 1LL*ret*x%mod;
 76             x = 1LL*x*x%mod;
 77             n >>= 1;
 78         }
 79         return ret;
 80     }
 81 
 82     int cal(vector<ll> &v) {
 83         if(v.size() < 19) {
 84             int pos = v.size()-1;
 85             ll ret = v[0];
 86             bool flag = false;
 87             if(v[0] >= mo[pos]) {
 88                 flag = true;
 89                 ret = ret%mo[pos] + mo[pos];
 90             }
 91             pos--;
 92             for(int i = 1;i < v.size(); i++) {
 93                 if(flag) {
 94                     ret = (pow_mod(2, ret, mo[pos]) +v[i])%mo[pos] + mo[pos];
 95                 }
 96                 else {
 97                     if(ret >= 30) {
 98                         flag = true;
 99                         ret = (pow_mod(2, ret, mo[pos]) + v[i])%mo[pos]+mo[pos];
100                     }
101                     else if(pow2[ret] >= mo[pos]) {
102                         flag = true;
103                         ret = (pow_mod(2, ret, mo[pos]) + v[i])%mo[pos] + mo[pos];
104                     }
105                     else {
106                         ret = pow2[ret] + v[i];
107                         if(ret >= mo[pos]) {
108                             flag = true;
109                             ret = ret%mo[pos] + mo[pos];
110                         }
111                     }
112                 }
113                 pos--;
114             }
115             return ret%MOD;
116         }
117         else {
118             ll ret = 1;
119             int pos = 18;
120             bool flag = true;
121             for(int i = v.size()-18;i < v.size(); i++) {
122                 ret = (pow_mod(2, ret, mo[pos]) + v[i])%mo[pos] + mo[pos];
123                 pos--;
124             }
125             return ret%MOD;
126         }
127     }
128 
129     void modify(int rt, int l, int r, int x) {
130         if(l == r) {
131             if(mark[rt]) {
132                 vt[l][vt[l].size()-1] += mark[rt];
133                 mark[rt] = 0;
134             }
135             vt[l].push_back(0);
136             sum[rt] = cal(vt[l]);
137             return ;
138         }
139         down(rt);
140         int mid = l+r>>1;
141         if(x <= mid)    modify(lson, x);
142         else    modify(rson, x);
143         up(rt);
144     }
145 
146     int query(int rt, int l, int r, int L, int R) {
147         if(L <= l && R >= r)    return sum[rt];
148         down(rt);
149         int mid = l+r>>1, ret = 0;
150         if(L <= mid)    Add(ret, query(lson, L, R));
151         if(R > mid) Add(ret, query(rson, L, R));
152         up(rt);
153         return ret;
154     }
155 }tree;
156 
157 int n, m;
158 
159 void init() {
160     for(int i = 0;i <= 30; i++) pow2[i] = 1<<i;
161 }
162 
163 int main() {
164     init();
165     int op, l, r, x;
166     while(scanf("%d%d", &n, &m) == 2) {
167         tree.build(1, 1, n);
168         while(m--) {
169             scanf("%d", &op);
170             if(op == 1) {
171                 scanf("%d%d", &l, &r);
172                 printf("%d\n", tree.query(1, 1, n, l, r));
173             }
174             else if(op == 2) {
175                 scanf("%d", &x);
176                 tree.modify(1, 1, n, x);
177             }
178             else {
179                 scanf("%d%d%d", &l, &r, &x);
180                 tree.update(1, 1, n, l, r, x);
181             }
182         }
183     }
184     return 0;
185 }

 

还没看懂数论那部分怎么搞的。。

hdu 5152 A Strange Problem线段树+欧拉函数

标签:

原文地址:http://www.cnblogs.com/usedrosee/p/4189664.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!