Array
题目描述
Yukikaze received an array (a1,a2,⋯an)as a gift. She decided to play with it. The game consists of q turns. In each turn, she will perform some kind of operation (listed below) on all elements in a subarray of a.
In this problem, we define that 00=1.
Since the result of operations of the last two kinds may be large, you only have to find it modulo a small integer p.
输入
Input
The first line of the input contains two integers n,p (1≤n≤105,2≤p≤30), denoting the number of elements in the array a and the modulus for the operations of type 4 and 5.
The next line contains n integers a1,a2,⋯,an (0≤ai≤109), denoting the initial elements in the array a.
The third line contains one integer q (1≤q≤105), denoting the number of operations to be performed.
Each of the following q lines contains 4 integers t,l,r,k (1≤t≤5,1≤l≤r≤n,0≤k≤109) represents an operation of kind t. Note that if t=5, it’s guaranteed that k=0.
输出
For each operation of type 4 or 5, output the result modulo p as an integer in a single line.
Sample Input
5 29
5 2 4 1 3
9
4 2 4 1
1 1 3 2
2 2 4 3
3 3 5 2
5 3 3 0
4 1 5 2
2 3 5 0
3 2 4 0
4 3 4 1
Sample Output
7
5
3
2
解题思路
本题很显然是个线段树。先说整体思路,然后我们再细细研究
1.我们宏观上需要实现的是查询和与积,但是这里的每个元素都是相互独立的。那么我们完全可以先统计他们的个数,然后再计算。因此我们计算用到了以下两个代码
ans += EularPow(i, k, mod) * cnt[i];
ans %= mod;
ans *= EularPow(i, cnt[i], mod);
ans %= mod;
这里应该一眼就能看出来含义
2.我们需要设计30棵树来维护,因为他们的每个值都在0-30之间,那么,我们维护每棵树的元素个数就可以了。
3.我们需要设计懒惰标记。我们这里懒惰标记表示当前这个懒惰标记对应的值,应该转换成什么值。这里拿纸笔画一画自然就明了了。为了明确,还是举个例子。
比如当前我的懒惰标记是1 2 3 4 5,但是父亲的懒惰标记是 1 8 27 64 125,这样我们可以理解,所有的1号都变成了父亲对应值1,2对应8,3对应27等等
当我们计算的时候,我们当前的懒惰标记下传就会改变当前的懒惰标记,以实现值的修改。
4.值的修改就是从某棵树上删除,然后另一棵树上增加
5.查询,把遍历的数量结果统计出来
6.计算pow时候需要用到欧拉降幂。亲测,不用欧拉降幂会TLE,这里就是一步优化。
7.输入输出挂会被卡
8.用longlong增大了运算量,会被卡
接下来会放出欧拉降幂的代码
a b ≡ { a b % φ ( p ) g c d ( a , p ) = 1 a b g c d ( a , p ) ≠ 1 , b < φ ( p ) a b % φ ( p ) + φ ( p ) g c d ( a , p ) ≠ 1 , b ≥ φ ( p ) ( m o d p ) a^{b}\equiv \left\{\begin{matrix} a^{b\%\varphi (p)} &gcd(a,p)=1 \\ a^{b}&gcd(a,p)\neq 1,b<\varphi(p) \\ a^{b\%\varphi (p)+\varphi (p)}&gcd(a,p)\neq 1,b\ge \varphi(p) \end{matrix}\right.\quad (mod\; p) ab≡⎩⎨⎧ab%φ(p)abab%φ(p)+φ(p)gcd(a,p)=1gcd(a,p)=1,b<φ(p)gcd(a,p)=1,b≥φ(p)(modp)
ll EularPow(ll a, ll b, ll mod) {
ll ans = 1;
if (gcd(a, mod) == 1)b = b % phi;
else if (b >= phi)b = b % phi + phi;
while (b > 0) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
至于phi的值需要用欧拉函数来解,这里一并放出
ll eular(ll n)
{
ll ans = n;
for (ll i = 2; i * i <= n; i++)
if (n % i == 0) {
ans = ans / i * (i - 1); while (n % i == 0)n /= i; }
if (n > 1)ans = ans / n * (n - 1); return ans;
}
思路分析完毕
Accept Code
#include<unordered_map>
#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const ll less_inf = 0x3f3f3f3f;
const char char_inf = 127;
#pragma GCC optimize(2)
#pragma warning(disable:6031)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false)
#define PI 3.141592653589793
#define EPS 1.0e-8
ll gcd(ll a, ll b) {
return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
return a / gcd(a, b) * b;
}
inline ll read() {
ll c = getchar(), Nig = 1, x = 0;
while (!isdigit(c) && c != '-')c = getchar();
if (c == '-')Nig = -1, c = getchar();
while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
return Nig * x;
}
inline void out(ll a) {
if (a < 0)putchar('-'), a = -a;
if (a > 9)out(a / 10);
putchar(a % 10 + '0');
}
ll qpow(ll x, ll n, ll mod) {
ll res = 1;
while (n > 0) {
if (n & 1)res = (res * x) % mod;
x = (x * x) % mod;
n >>= 1;
}
return res;
}
#define read read()
const int N = 100005;
int mod;
int tree[N << 2][31];
int lazy[N << 2][31];
int temp[31];
int cnt[31];
int tot = 0;
vector<int>save;
int phi;
ll eular(ll n)
{
ll ans = n;
for (ll i = 2; i * i <= n; i++)
if (n % i == 0) {
ans = ans / i * (i - 1); while (n % i == 0)n /= i; }
if (n > 1)ans = ans / n * (n - 1); return ans;
}
ll EularPow(ll a, ll b, ll mod) {
ll ans = 1;
if (gcd(a, mod) == 1)b = b % phi;
else if (b >= phi)b = b % phi + phi;
while (b > 0) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
void push_up(int rt)
{
for (int i = 0; i < mod; i++)
tree[rt][i] = tree[rt << 1][i] + tree[rt << 1 | 1][i];
}
void push_down(int rt)
{
for (int i = 0; i < mod; i++)
{
temp[i] = tree[rt << 1][i];
tree[rt << 1][i] = 0;
}
for (int i = 0; i < mod; i++)
tree[rt << 1][lazy[rt][i]] += temp[i];
for (int i = 0; i < mod; i++)
{
temp[i] = tree[rt << 1 | 1][i];
tree[rt << 1 | 1][i] = 0;
}
for (int i = 0; i < mod; i++)
tree[rt << 1 | 1][lazy[rt][i]] += temp[i];
for (int i = 0; i < mod; i++)
{
lazy[rt << 1][i] = lazy[rt][lazy[rt << 1][i]];
lazy[rt << 1 | 1][i] = lazy[rt][lazy[rt << 1 | 1][i]];
}
for (int i = 0; i < mod; i++)lazy[rt][i] = i;
}
void creat(int l, int r, int rt)
{
if (l == r)
{
tree[rt][save[tot++] % mod]++;
return;
}
for (int i = 0; i < mod; i++)
lazy[rt][i] = i;
int mid = l + r >> 1;
creat(l, mid, rt << 1);
creat(mid + 1, r, rt << 1 | 1);
push_up(rt);
}
ll change(ll num, ll val, ll ord)
{
switch (ord)
{
case 1:return (num + val) % mod;
case 2:return (num * val) % mod;
default:return EularPow(num, val, mod);
}
}
void update(int ord, int k, int L, int R, int l, int r, int rt)
{
if (L <= l && r <= R)
{
for (int i = 0; i < mod; i++)
{
temp[i] = tree[rt][i];
tree[rt][i] = 0;
}
for (int i = 0; i < mod; i++)
{
int num = change(i, k, ord);
lazy[rt][i] = change(lazy[rt][i], k, ord);
tree[rt][num] += temp[i];
}
return;
}
push_down(rt);
int mid = l + r >> 1;
if (L <= mid)update(ord, k, L, R, l, mid, rt << 1);
if (R > mid)update(ord, k, L, R, mid + 1, r, rt << 1 | 1);
push_up(rt);
}
void query(int L, int R, int l, int r, int rt)
{
if (L <= l && r <= R)
{
for (int i = 0; i < mod; i++)
cnt[i] += tree[rt][i];
return;
}
push_down(rt);
int mid = l + r >> 1;
if (L <= mid)query(L, R, l, mid, rt << 1);
if (R > mid)query(L, R, mid + 1, r, rt << 1 | 1);
}
int main()
{
int n;
scanf("%d%d", &n, &mod);
phi = eular(mod);
for (int i = 0; i < n; i++)
{
int t;
scanf("%d", &t);
save.push_back(t);
}
creat(1, n, 1);
int T;
scanf("%d", &T);
while (T--)
{
int ord, l, r, k;
scanf("%d%d%d%d", &ord, &l, &r, &k);
if (ord <= 3)
update(ord, k, l, r, 1, n, 1);
else if (ord == 4)
{
memset(cnt, 0, sizeof(cnt));
query(l, r, 1, n, 1);
int ans = 0;
for (int i = 0; i < mod; i++)
{
ans += EularPow(i, k, mod) * cnt[i];
ans %= mod;
}
printf("%d\n", ans);
}
else
{
memset(cnt, 0, sizeof(cnt));
query(l, r, 1, n, 1);
int ans = 1;
for (int i = 0; i < mod; i++)
{
ans *= EularPow(i, cnt[i], mod);
ans %= mod;
}
printf("%d\n", ans);
}
}
}