牛客练习赛22-E-简单数据结构1(树状数组+欧拉线性筛+降幂公式)

链接:https://www.nowcoder.com/acm/contest/132/E
来源:牛客网
 

题目描述

给一个长为n的序列,m次操作,每次操作:

1.区间

2.对于区间,查询 ,一直到-

请注意每次的模数不同。

输入描述:

第一行两个整数 n,m 表示序列长度和操作数

接下来一行,n个整数,表示这个序列

接下来m行,可能是以下两种操作之一:

操作1:区间[l,r]加上 x

操作2:查询区间[l,r]的那个式子mod p的值

输出描述:

对于每个询问,输出一个数表示答案

示例1

输入

复制

6 4
1 2 3 4 5 6
2 1 2 10000007
2 2 3 5
1 1 4 1
2 2 4 10

输出

复制

1
3
1

备注:

n , m <= 500000

序列中每个数在 [1,2e9] 内,x <= 2e9 , p <= 2e7

降幂公式的简单应用,存一发欧拉线性筛的板子。。。。。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 500005
#define mod 20000007
#define ll long long
bool isp[mod];
ll c[maxn],a[maxn];
int pri[mod/10],phi[mod];
void init(int n)//欧拉函数线性筛
{
	int p=0;
	for(int i=2;i<=n;i++)
	{
		if(isp[i]==0)
			pri[++p]=i,phi[i]=i-1;
		for(int j=1;j<=p && i*pri[j]<=n;j++)
		{
			isp[i*pri[j]]=1;
			if(i%pri[j]==0)
			{
				phi[i*pri[j]]=phi[i]*pri[j];
				break;
			}
			else
				phi[i*pri[j]]=phi[i]*(pri[j]-1);
		}
	}
}
ll Mod(ll x,ll y)
{
	return x>=y?(x%y+y):x;
}
ll q(ll x,ll y,ll p)
{
	ll res=1;
	while(y)
	{
		if(y%2)
			res=Mod(res*x,p);
		x=Mod(x*x,p);
		y/=2;
	}
	return res;
}
void sum(ll x,ll d,ll n)
{
	while(x<=n)
		c[x]+=d,x+=x&-x;
}
ll find(ll x)
{
	ll res=0;
	while(x)
		res+=c[x],x-=x&-x;
	return res;
}
ll dfs(ll l,ll r,ll p)
{
	ll val=find(l);
	if(l==r || p==1)
		return Mod(val,p);
	return q(Mod(val,p),dfs(l+1,r,phi[p]),p);
}
int main(void)
{
	init(mod-5);
	int n,q;
	ll l,r,t,x;
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		sum(i,a[i]-a[i-1],n);
	}
	while(q--)
	{
		scanf("%lld%lld%lld%lld",&t,&l,&r,&x);
		if(t==1)
			sum(l,x,n),sum(r+1,-x,n);
		else
			printf("%lld\n",dfs(l,r,x)%x);
	}
	return 0;
}
/*
6 4
1 2 3 4 5 6
2 1 2 10000007
2 2 3 5
1 1 4 1
2 2 4 10
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值