【CUGBACM15级BC第24场 C】hdu 5152 A Strange Problem

70 篇文章 0 订阅
34 篇文章 0 订阅

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


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(lir ) .

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 (1N,M50000) .
The second line contains N integers A1,A2,A3,...AN (1Ai109,1iN)
Each of the next M lines begin with a number type (1type3) .
If type=1   , there will be two integers more in the line: l,r (1lrN) , which correspond the operation 1.
If type=2   , there will be one integer more in the line: x (1xN) , which correspond the operation 2.
If type=3   , there will be three integers more in the line: l,r,x (1lrN,1x109) , 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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值