Codeforces Round #538 (Div. 2) F - Please, another Queries on Array?(数论,线段树)

Description:

给出一个大小为n的数列,有两种询问:

1. multiply l r x   :将l到r的每个元素乘x

2. totient l r: 输出\phi(\coprod_{i=1}^{n} a_i) 对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;
}

猜你喜欢

转载自blog.csdn.net/tomandjake_/article/details/87020825