Description:
给出一个大小为n的数列,有两种询问:
1. multiply l r x :将l到r的每个元素乘x
2. totient l r: 输出 对1e9+7的余数
Input:
n
ai(for 1<=i<=n)
Output:
answer
Analysis:
以下来自tutorial
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
#include<unordered_set>
#include<ctime>
#include<cstring>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
const int INF = 1 << 30;
const int maxn = 100005;
const int MOD = 1e9+7;
const double eps = 1e-6;
const int M = 301, B = 500;
const int phi = 1e9 + 6;
int P = 0;
int mul(int a, int b) {
return (a * 1ll * b) % MOD;
}
int mpow(int u, int p) {
if (!p)return 1;
return mul(mpow(mul(u, u), p / 2), (p & 1) ? u : 1);
}
vector<int> primes;
vector<int> pi;
int pw[M];
int lg[maxn];
bool isprime(int x) {
if (x <= 1)return false;
for (int i = 2; i*i <= x; ++i) {
if (x%i == 0)return false;
}
return true;
}
void precalc() {
_for(i,0,M)
if (isprime(i)) {
primes.push_back(i);
P++;
}
pi.resize(P);
_for(i, 0, M) {
int x = 1;
_for(j, 0, B) {
x = mul(x, i);
}
pw[i] = x;
}
_for(i, 0, P) {
pi[i] = mpow(primes[i], phi - 1);
}
}
LL transform(int x) {
LL mask = 0;
_for(i, 0, P) {
if (x%primes[i] == 0) {
mask |= (1LL << i);
}
}
return mask;
}
struct product_tree {
vector<int> arr, block_product, block_update, single_update;
int n;
product_tree(vector<int>& a) : n(a.size()) {
arr = a;
while (n % B) {
n++, arr.push_back(1);
}
block_product.resize(n / B, 1);
block_update.resize(n / B, -1);
single_update.resize(n / B, -1);
for (int i = 0; i < n; i += B) {
int x = 1;
int pos = i / B;
_for(j,0, B)
x = mul(x, arr[i + j]);
block_product[pos] = x;
}
}
inline void add(int& u, int x, int mode) {
if (mode) {
if (u == -1)
u = x;
else
u = mul(u, x);
}
else {
if (u == -1)
u = pw[x];
else
u = mul(u, pw[x]);
}
}
void update(int pos, int x) {
add(block_update[pos], x, 0);
add(single_update[pos], x, 1);
}
void reconstruct(int pos) {
int e = single_update[pos];
if (e == -1) return;
int x = 1;
int l = pos * B, r = l + B;
for (int i = l; i < r; i++) {
arr[i] = mul(arr[i], e);
x = mul(x, arr[i]);
}
single_update[pos] = block_update[pos] = -1;
block_product[pos] = x;
}
void apply(int l, int r, int x) {
int L = l / B, R = r / B;
if (L == R) {
reconstruct(L);
for (int i = l; i <= r; i++) {
arr[i] = mul(arr[i], x);
block_product[L] = mul(block_product[L], x);
}
return;
}
reconstruct(L);
for (int i = l; i < (L + 1) * B; i++) {
arr[i] = mul(arr[i], x);
block_product[L] = mul(block_product[L], x);
}
reconstruct(R);
for (int i = R * B; i <= r; i++) {
arr[i] = mul(arr[i], x);
block_product[R] = mul(block_product[R], x);
}
for (int j = L + 1; j < R; j++)
update(j, x);
}
int get(int l, int r) {
int L = l / B, R = r / B;
int ans = 1;
if (L == R) {
reconstruct(L);
for (int i = l; i <= r; i++) {
ans = mul(ans, arr[i]);
}
return ans;
}
reconstruct(L);
for (int i = l; i < (L + 1) * B; i++) {
ans = mul(ans, arr[i]);
}
reconstruct(R);
for (int i = R * B; i <= r; i++) {
ans = mul(ans, arr[i]);
}
for (int j = L + 1; j < R; j++) {
ans = mul(ans, block_product[j]);
if (block_update[j] != -1)
ans = mul(ans, block_update[j]);
}
return ans;
}
};
struct prime_tree {
vector<LL> t, d;
int n;
prime_tree(vector<LL>& a) : n(a.size()) {
t.resize(4 * n);
d.resize(4 * n, -1);
build(1, 0, n, a);
}
LL build(int u, int l, int r, vector<LL>& a) {
if (l == r - 1) {
return t[u] = a[l];
}
int m = (l + r) / 2;
return t[u] = build(u << 1, l, m, a) | build(u << 1 | 1, m, r, a);
}
inline void add(LL& u, LL x) {
if (u == -1)
u = x;
else
u |= x;
}
void push(int u, int l, int r) {
if (d[u] == -1) return;
t[u] |= d[u];
if (r - l > 1) {
add(d[u << 1], d[u]);
add(d[u << 1 | 1], d[u]);
}
d[u] = -1;
}
void update(int u, int l, int r, int L, int R,LL x) {
push(u, l, r);
if (L >= R || l > L || r < R) return;
if (l == L && r == R) {
add(d[u], x);
push(u, l, r);
return;
}
int m = (l + r) / 2;
update(u << 1, l, m, L, min(m, R), x);
update(u << 1 | 1, m, r, max(L, m), R, x);
t[u] = t[u << 1] | t[u << 1 | 1];
}
LL get(int u, int l, int r, int L, int R) {
push(u, l, r);
if (L >= R || l > L || r < R) return 0;
if (l == L && r == R) {
return t[u];
}
int m = (l + r) / 2;
return get(u << 1, l, m, L, min(m, R)) | get(u << 1 | 1, m, r, max(L, m), R);
}
LL get(int l, int r) {
return get(1, 0, n, l, r + 1);
}
void apply(int l, int r,LL x) {
update(1, 0, n, l, r + 1, x);
}
};
void solve() {
int n, q; cin >> n >> q;
vector<int> a(n);
vector<LL> _a;
for (auto & v : a) {
cin >> v;
_a.push_back(transform(v));
}
auto Ptree = product_tree(a);
auto Mtree = prime_tree(_a);
int l, r, x;
_for(i, 0, q) {
string s; cin >> s;
if (s == "MULTIPLY") {
cin >> l >> r >> x;
l--; r--;
Ptree.apply(l, r, x);
Mtree.apply(l, r, transform(x));
}
else {
cin >> l >> r;
l--; r--;
int product = Ptree.get(l, r);
LL mask = Mtree.get(l, r);
_for(j, 0, 63) {
if (mask >> j & 1) {
product = mul(product, primes[j] - 1);
product = mul(product, pi[j]);
}
}
cout << product << endl;
}
}
}
int main()
{
//freopen("C:\\Users\\admin\\Desktop\\in.txt", "r", stdin);
//freopen("C:\\Users\\admin\\Desktop\\out.txt", "w", stdout);
ios_base::sync_with_stdio(0);//用这个
cin.tie(0); //就能防止cin超时orz
int t = 1;
precalc();
while (t--) {
solve();
}
return 0;
}