hdu 5152 A Strange Problem

hdu 5152 A Strange Problem

题目链接

点击打开链接

题意:

给你一个长度为N的序列,序列为A1,A2,A3,...AN,然后有M个操作,每个操作为以下三种操作的其中一个:
1. 输出操作。给你l,r,输出∑i=lrAi的值。
2. 修改操作。给你x,把Ax修改为2Ax
3. 加法操作。给你l,r,x,给Ai(l≤i≤r)加上x
由于输出操作的结果可能很大,输出结果对2333333取模。

限制:

0 <= n,m <= 50000 0 <= ai <= 1e9

思路:

首先是,这道题主要考操作2,公式x >= Phi(C), A^x = A ^ (x%Phi(C) + Phi(C)) (mod C)
然后,值得注意是,这道题的Phi(c),是一层套一层的。
最后,题目给出2333333,所以Phi(c),最多只有18层。

/*bc24c
  题意:给你一个长度为N的序列,序列为A1,A2,A3,...AN,然后有M个操作,每个操作为以下三种操作的其中一个:
  1. 输出操作。给你l,r,输出∑i=lrAi的值。
  2. 修改操作。给你x,把Ax修改为2Ax
  3. 加法操作。给你l,r,x,给Ai(l≤i≤r)加上x
  由于输出操作的结果可能很大,输出结果对2333333取模。
  限制:0 <= n,m <= 50000	0 <= ai <= 1e9
  思路:首先是,这道题主要考操作2,公式x >= Phi(C), A^x = A ^ (x%Phi(C) + Phi(C)) (mod C)
  然后,值得注意是,这道题的Phi(c),是一层套一层的。
  最后,题目给出2333333,所以Phi(c),最多只有18层。
 */
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define LL __int64
#define ls (n<<1)
#define rs (n<<1 | 1)
#define pb push_back
const int MAXN = 100005;
const int MOD = 2333333;
int mo[19] = { 2333333 , 2196720 , 580608 , 165888 , 55296 , 18432 , 6144 , 2048 , 1024 , 512 , 256 , 128 , 64 , 32 , 16 , 8 , 4 , 2 , 1 };
LL sum[MAXN << 2];
LL len[MAXN << 2];
LL add[MAXN << 2];
LL a[MAXN];
vector<LL> tab[MAXN];
int n,m;
int fpow(LL a,LL b,LL mod){
	LL ret = 1;
	a %= MOD;
	while(b){
		if(b & 1) ret = ret * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return ret;
}
void down(int n){
	if(add[n]){
		add[ls] += add[n];
		add[rs] += add[n];
		sum[ls] = (sum[ls] + add[n] * len[ls] % MOD) % MOD;
		sum[rs] = (sum[rs] + add[n] * len[rs] % MOD) % MOD;
		add[n] = 0;
	}
}
void up(int n){
	sum[n] = (sum[ls] + sum[rs]) % MOD;
}
void build(int l,int r,int n){
	add[n] = 0;
	len[n] = r - l + 1;
	if(l == r){
		sum[n] = a[l]%MOD;
		return ;
	}
	int mid = (l + r) >> 1;
	build(l,mid,ls);
	build(mid+1,r,rs);
	up(n);
}
void update(int L,int R,int l,int r,int n,LL v){
	if(L <= l && r <= R){
		add[n] += v;
		sum[n] = (sum[n] + len[n] * v) % MOD;
		return ;
	}
	down(n);
	int mid = (l + r) >> 1;
	if(L <= mid) update(L,R,l,mid,ls,v);
	if(mid < R) update(L,R,mid+1,r,rs,v);
	up(n);
}
LL cal(int i,int t){
	if(t == 19) return 0;
	LL tmp;
	int ch = tab[i].size()-1-t;
	if(t+1 == tab[i].size()) tmp = tab[i][ch];
	else tmp = fpow(2,cal(i,t+1),mo[t]) + tab[i][ch];
	if(tmp >= mo[t]) tmp = tmp % mo[t] + mo[t];
	return tmp;
}
void modify(int x,int l,int r,int n){
	if(l == r){
		tab[x][tab[x].size()-1]+=add[n];
		add[n] = 0;
		tab[x].pb(0);
		sum[n] = cal(x,0) % MOD;
		return ;
	}
	down(n);
	int mid = (l + r) >> 1;
	if(x <= mid) modify(x,l,mid,ls);
	else modify(x,mid+1,r,rs);
	up(n);
}
LL query(int L,int R,int l,int r,int n){
	if(L <= l && r <= R) return sum[n];
	down(n);
	int mid = (l + r) >> 1;
	LL ret = 0;
	if(L <= mid) ret = (ret + query(L,R,l,mid,ls)) % MOD;
	if(mid < R) ret = (ret + query(L,R,mid+1,r,rs)) % MOD;
	return ret;
}
void init(){
	for(int i=0;i<=n;++i)
		tab[i].clear();
}
int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		init();
		for(int i=1;i<=n;++i){
			scanf("%I64d",&a[i]);
			tab[i].pb(a[i]);
		}
		build(1,n,1);
		int op,u,v;
		LL w;
		for(int i=0;i<m;++i){
			scanf("%d",&op);
			if(op==1){
				scanf("%d%d",&u,&v);
				printf("%I64d\n",query(u,v,1,n,1));
			}
			else if(op == 2){
				scanf("%d",&u);
				modify(u,1,n,1);
			}
			else{
				scanf("%d%d%I64d",&u,&v,&w);
				update(u,v,1,n,1,w);
			}
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值