题意:给你一个数列
有两个查询:(1)计算区间【l,r】的ala(l+1)a(l+2)^…ar%mod;
(2)给区间【l,r】每个数加x;
题解:使用欧拉降幂和递归可以简单的完成第一种操作,但每次每次的模数不同,所以要先用欧拉筛筛一遍,得到范围内的每个数的欧拉值
接着就是区间修改,一个个改肯定不行,这里就要用到差值维护,差值即 a1,a2-a1,a3-a2,a4-a3…an-a(n-1),那改变区间【l,r】的值对差值的影响只有第l个和第r+1个有影响,即每次区间修改只需要修改两个值即可
欧拉筛模板:
void sevice()
{
ll ans = 0;
phi[1] = 1;
for (int i = 2; i < maxn; i++)
{
if (!phi[i])
{
prime[ans++] = i;
phi[i] = i - 1;
}
for (int j = 0; i*prime[j] < maxn&&j < ans; j ++ )
{
if (i%prime[j] == 0)
{
phi[i*prime[j]] = phi[i] * prime[j];
break;
}
else phi[i*prime[j]] = phi[i] * (prime[j] - 1);
}
}
}在这里插入代码片
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e7 + 5;
const int N = 5e5 + 5;
ll n;
ll phi[maxn];
ll prime[maxn];
ll g[N];
ll bits(int x)
{
return x&(-x);
}
void update(ll x,ll y)
{
while(x<=n)
{
g[x] += y;
x+=bits(x);}
}
ll getsum(ll x)
{
ll val=0;
while(x>0)
{
val+=g[x];
x-=bits(x);
}
return val;
}
void update(ll r, ll l, ll c)
{
update(r, c);
update(l+1, -c);
}
void sevice()
{
ll ans = 0;
phi[1] = 1;
for (int i = 2; i < maxn; i++)
{
if (!phi[i])
{
prime[ans++] = i;
phi[i] = i - 1;
}
for (int j = 0; i*prime[j] < maxn&&j < ans; j ++ )
{
if (i%prime[j] == 0)
{
phi[i*prime[j]] = phi[i] * prime[j];
break;
}
else phi[i*prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
ll mod(ll a, ll b)
{
return (a>b?(a%b+b):a);
}
ll qpow(ll a, ll b, ll p)
{
a = mod(a,p);
ll ans=1;
while (b)
{
if (b & 1)
ans = mod(ans*a, p);
a = mod(a*a, p);
b/=2;
}
return ans;
}
ll solve(ll l, ll r, ll p)
{
ll kk = getsum(l);
//cout << p << endl;
if (l == r || p == 1)return mod(kk, p);
else {
return qpow(kk, solve(l + 1, r, phi[p]), p);
}
}
int main()
{
sevice();
/*for (int i = 0; i < 10; i++)
cout << phi[i] << endl;*/
int m;
scanf("%lld%d",&n,&m);
ll t2;
ll t1 = 0;
memset(g, 0, sizeof(g + N));
for (int i = 1; i <= n; i++)
{
scanf("%lld",&t2);
update(i, t2 - t1);
t1 = t2;
}ll a, l, r, p;
while (m--)
{
scanf("%lld%lld%lld%lld",&a,&l,&r,&p);
//cin >> a >> l >> r >> p;
if (a == 2)
{
printf("%lld\n",solve(l,r,p)%p);
//cout << solve(l, r, p) << endl;
//cout << getsum(l) << endl;
}if (a == 1)
update(l, r, p);
}
}
在这里插入代码片