A Strange Problem
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 484 Accepted Submission(s): 119
Total Submission(s): 484 Accepted Submission(s): 119
Problem Description
You are given a strange problem. First you have got a sequence contains
N
integers
A1,A2,A3,...AN
.Then you should perform a sequence of
M
operations. An operation can be one of the following:
1. Print operation l,r . Print the value of ∑i=lrAi .
2. Modify operation x . Modify Ax to 2Ax
3. Add operation l,r,x . Add xtoAi(l≤i≤r ) .
As the value of print operation can be rather large, print the remainder after dividing the number by 2333333 .
1. Print operation l,r . Print the value of ∑i=lrAi .
2. Modify operation x . Modify Ax to 2Ax
3. Add operation l,r,x . Add xtoAi(l≤i≤r ) .
As the value of print operation can be rather large, print the remainder after dividing the number by 2333333 .
Input
There are several test cases.
In each test case:
The first line contains two integers N,M (1≤N,M≤50000) .
The second line contains N integers A1,A2,A3,...AN (1≤Ai≤109,1≤i≤N)
Each of the next M lines begin with a number type (1≤type≤3) .
If type=1 , there will be two integers more in the line: l,r (1≤l≤r≤N) , which correspond the operation 1.
If type=2 , there will be one integer more in the line: x (1≤x≤N) , which correspond the operation 2.
If type=3 , there will be three integers more in the line: l,r,x (1≤l≤r≤N,1≤x≤109) , which correspond the operation 3.
In each test case:
The first line contains two integers N,M (1≤N,M≤50000) .
The second line contains N integers A1,A2,A3,...AN (1≤Ai≤109,1≤i≤N)
Each of the next M lines begin with a number type (1≤type≤3) .
If type=1 , there will be two integers more in the line: l,r (1≤l≤r≤N) , which correspond the operation 1.
If type=2 , there will be one integer more in the line: x (1≤x≤N) , which correspond the operation 2.
If type=3 , there will be three integers more in the line: l,r,x (1≤l≤r≤N,1≤x≤109) , which correspond the operation 3.
Output
For each Print operation, output the remainder of division of the value by
2333333
.
Sample Input
3 4 1 2 3 2 3 1 2 3 3 1 3 2 1 1 3 2 2 5 2 2 1 1 1 2
Sample Output
10 17 34
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL __int64
#define eps 1e-8
#define INF INT_MAX
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int MOD = 2333333;
const int maxn = 50000 + 5;
int phi[20] = {2333333 , 2196720 , 580608 , 165888 , 55296 , 18432 , 6144 ,
, 1024 , 512 , 256 , 128 , 64 , 32 , 16 , 8 , 4 , 2 , 1
};
LL sum[maxn << 2] , add[maxn << 2];
vector <LL> a[maxn];
int pow2[33];
void init()
{
//求2 ^ i
for (int i = 0 ; i <= 30 ; i++)
{
pow2[i] = 1 << i;
}
}
LL pow_mod(LL a , LL i , LL n)
{
// a ^ i % n的快速幂
if (i == 0)
{
return 1;
}
LL tmp = pow_mod(a , i >> 1 , n);
tmp = tmp * tmp % n;
if (i & 1)
{
tmp = tmp * a % n;
}
return tmp;
}
void PushUp(int rt)
{
sum[rt] = (sum[rt << 1] + sum[rt << 1 | 1]) % MOD;
}
void build(int l , int r , int rt)
{
add[rt] = 0;
if (l == r)
{
a[l].clear(); //清零不要忘了
scanf("%d" , &sum[rt]);
a[l].push_back(sum[rt]); //初始值放入a[l][0]
sum[rt] %= MOD;
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
void PushDown(int rt , int len)
{
if (add[rt])
{
add[rt << 1] += add[rt];
add[rt << 1 | 1] += add[rt];
sum[rt << 1] = (sum[rt << 1] + 1LL * (len - (len >> 1)) * add[rt]) % MOD;
sum[rt << 1 | 1] = (sum[rt << 1 | 1] + 1LL * (len >> 1) * add[rt]) % MOD;
add[rt] = 0;
}
}
void update(int L , int R , int x , int l , int r , int rt)
{
if (L <= l && R >= r)
{
sum[rt] = (sum[rt] + 1LL * (r - l + 1) * x) % MOD;
add[rt] += x;
return;
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
if (L > m)
{
update(L , R , x , rson);
}
else if (R <= m)
{
update(L , R , x , lson);
}
else
{
update(L , R , x , lson);
update(L , R , x , rson);
}
PushUp(rt);
}
int cal(vector <LL> a)
{
LL num;
if (a.size() < 19) //没到18层,所以要全部来一遍
{
num = a[0];
bool flag = false; //flag判断是否满足 x >= Phi(C)
int pos = a.size() - 1;
if (num >= phi[pos])
{
flag = true;
num = num % phi[pos] + phi[pos];
}
pos--;
for (int i = 1 ; i < a.size(); i++ , pos--)
{
if (flag)
{
num = (pow_mod(2 , num , phi[pos]) + a[i]) % phi[pos] + phi[pos];
}
else
{
if (num >= 30)
{
flag = true;
num = (pow_mod(2 , num , phi[pos]) + a[i]) % phi[pos] + phi[pos];
}
else
{
num = pow2[num] + a[i]; //这时就是 2 ^ num + a[i]
if (num >= phi[pos])
{
flag = true;
num = num % phi[pos] + phi[pos];
}
}
}
}
}
else //由于Phi[18]就等于1了,所以之前取余就都等于0,不管就可以了
{
num = 1;
int pos = 17;
for (int i = a.size() - 18 ; i < a.size() ; i++ , pos--)
{
num = (pow_mod(2 , num , phi[pos]) + a[i]) % phi[pos] + phi[pos];
}
}
return num % MOD;
}
void modify(int p , int l , int r , int rt)
{
if (l == r)
{
if (add[rt]) //保留操作3的信息
{
a[p][a[p].size() - 1] += add[rt];
add[rt] = 0;
}
a[p].push_back(0); //加一层
sum[rt] = cal(a[p]);
return;
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
if (p <= m)
{
modify(p , lson);
}
else
{
modify(p , rson);
}
PushUp(rt);
}
int query(int L , int R , int l , int r , int rt)
{
if (L <= l && R >= r)
{
return sum[rt] % MOD;
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
if (L > m)
{
return query(L , R , rson);
}
else if (R <= m)
{
return query(L , R , lson);
}
else
{
return (query(L , R , lson) + query(L , R , rson)) % MOD;
}
}
int main()
{
init();
int a , b , c , n , m , ch;
while (~scanf("%d %d" , &n , &m))
{
build(1 , n , 1);
while (m--)
{
scanf("%d" , &ch);
if (ch == 1)
{
scanf("%d %d" , &a , &b);
printf("%d\n" , query(a , b , 1 , n , 1));
}
else if (ch == 2)
{
scanf("%d" , &c);
modify(c , 1 , n , 1);
}
else
{
scanf("%d %d %d" , &a , &b , &c);
update(a , b , c , 1 , n , 1);
}
}
}
return 0;
}