1. 程式人生 > >Newcoder 148 A.Rikka with Lowbit(水~)

Newcoder 148 A.Rikka with Lowbit(水~)

Description

給出一個長度為nn的序列,定義操作f(x)f(x)0.50.5概率把f(x)=xlowbit(x)f(x)=x-lowbit(x)0.50.5概率f(x)=x+lowbit(x)f(x)=x+lowbit(x),現在對這個序列做mm次操作,操作有兩種:

1LR:1\ L\ R:aia_i變成f(ai),LiRf(a_i),L\le i\le R

2LR:2\ L\ R:查詢區間和i=LRai\sum\limits_{i=L}^Ra_i

=LRai的期望

Input

第一行一整數TT表示用例組數,每組用例首先輸入兩個整數n,mn,m,之後輸入nn個整數aia_i,最後mm行每行一個操作

(1T3,1n,m105,1ai108)(1\le T\le 3,1\le n,m\le 10^5,1\le a_i\le 10^8)

Output

對於每次查詢操作,假設區間和為ww,則輸出w2nmmod998244353w\cdot 2^{nm}\ mod\ 998244353

Sample Input

1 3 6 1 2 3 1 3 3 2 1 3 1 3 3 2 1 3 1 1 3 2 1 3

Sample Output

1572864 1572864 1572864

Solution

f(x)f(x)期望為xx,而每個位置相互獨立,故求和期望即為期望求和,查詢操作變成查詢原先序列區間和

Code

#include<cstdio>
using namespace std;
typedef long long ll;
#define maxn 100005
#define mod 998244353
int mul(int x,int y)
{
	ll z=1ll*x*y;
	return z-z/mod*mod;
}
int add(int x,int y)
{
	x+=y;
	if(x>=mod)x-=mod;
	return x;
}
int Pow(int x,ll y)
{
	int ans=1;
	while(y)
	{
		if(y&1)ans=mul(ans,x);
		x=mul(x,x);
		y>>=1;
	}
	return ans;
}
int T,n,m,a[maxn];
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]=add(a[i],a[i-1]);
		int res=Pow(2,(ll)n*m);
		while(m--)
		{
			int op,l,r;
			scanf("%d%d%d",&op,&l,&r);
			if(op==2)
			{
				printf("%d\n",mul(add(a[r],mod-a[l-1]),res));
			}
		}
	}
	return 0;
}