[Bzoj4026] dC Loves Number Theory_ President tree _ _ Euler function prime factorization of

dC Loves Number Theory

Topic effect : dC After a few seconds, all of the topics on BZOJ, feeling Meng Meng da, came up with such a water problem, to save the depleting water resources problem. Given a length n of the sequence of positive integers A, there are times query q, each query within a range of all the elements of the product of φ (φ (n) representative of the counted number 1 ~ n with n prime). Since the answer may be large, so please to answer mod 10 ^ 6 + 777. (This question by force, all inquiries operations l, r needs on a xor answer to the query lastans, initially, lastans = 0)

Data range :. 1 <= N <= 50000, . 1 <= Q <= 100000, . 1 <= Ai <^ = 10. 6.


answer:

Will not .....

I listened $ lijinnn $ talked realize.

There is a very, very important property, then if not found simply can not do.

We consider how to engage in violence: Each full scan again, and then statistical answer.

This is too violent .... we optimize optimization.

In this way, each location to open a length of up to $ 7 $ array represents the current position of the prime factors because we know:

$\varphi(n) = n*\prod\limits_{p_i|n} \frac{p_i - 1}{p_i}$。

This complexity is $ O (n ^ 2 \ times 7) $ a.

Re-optimization optimization? ? ?

We found that for each of the left, I can maintain the position of each quality factor leftmost appear to the right of the left end of the current point.

Is the first sweep over the entire array, first find out the position of the left point at the $ 1 $ for each prime number appears in the left-most.

Then each, move the left point to the right, update the current position of the left end point where all the answers to the quality factor value, this query is then checked at the left end point like corresponding to the array, which is $ O (n) $ of.

OK, now to the complexity of the $ O (n ^ 2) $, the focus is to maintain the quality factor in each case no more than the left point, the left-most position.

That positive solution does not come out yet!

We found that the left point once every move, change the value of a maximum of only $ 7 $, and the remaining values ​​are the same.

What can maintain this? That is, a lot of the same, only a few different

Chairman of the tree Yeah, we point to open a chairman for each tree left, directly maintain just said array.

How to maintain it?

For the first $ i $ is the chairman stars tree, if there is a prime number $ p $ in $ i $ the left side of the left-most position $ j $, then the Chairman of the tree $ j $ position $ * = \ frac {p - 1} {p} $, then the President tree node maintains all product numbers dominated interval.

However, each individual prime factor decomposition point $ O (n \ sqrt {a_i}) ​​$, we pretreated mass by number, and then enumerating primes were larger complexity is a harmonic series $ O (nln \ n) $.

Chairman of the complexity of the tree is $ O (nlogn) $, each $ O (loglogn) $, with the total complexity is $ O (nlognloglogn + nln \ n) $.

Code :

#include <bits/stdc++.h>

#define N 50010 

using namespace std;

const int mod = 1000777 ;

typedef long long ll;

vector <int> v[1000010 ];

int prime[1000010 ], cnt;

bool vis[1000010 ];

int pre[1000010 ], bfr[N], a[N];

int ls[N * 200], rs[N * 200], sum[N * 200], root[N * 200], tot;

char *p1, *p2, buf[100000];

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

int rd() {
	int x = 0, f = 1;
	char c = nc();
	while (c < 48) {
		if (c == '-')
			f = -1;
		c = nc();
	}
	while (c > 47) {
		x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
	}
	return x * f;
}

int qpow(int x, int y) {
	int ans = 1;
	while (y) {
		if (y & 1)
			ans = (ll)ans * x % mod;
		y >>= 1;
		x = (ll)x * x % mod;
	}
	return ans;
}

void init() {
	for (int i = 2; i <= 1000000; i ++ ) {
		if (!vis[i])
			prime[ ++ cnt] = i;
		for (int j = 1; j <= cnt && (ll)i * prime[j] <= 1000000; j ++ ) {
			vis[i * prime[j]] = true;
			if (i % prime[j] == 0) {
				break;
			}
		}
	}
}

void update(int x, int val, int l, int r, int pre, int &p) {
	p = ++tot;
	ls[p] = ls[pre];
	rs[p] = rs[pre];
	sum[p] = (ll)sum[pre] * val % mod;
	if (l == r) {
		return;
	}
	int mid = (l + r) >> 1;
	if (x <= mid)
		update(x, val, l, mid, ls[pre], ls[p]);
	else
		update(x, val, mid + 1, r, rs[pre], rs[p]);
}

int query(int x, int y, int l, int r, int p) {
	if (!p) {
		return 1;
	}
	if (x <= l && r <= y) {
		return sum[p];
	}
	int ans = 1, mid = (l + r) >> 1;
	if (x <= mid)
		ans = (ll)ans * query(x, y, l, mid, ls[p]) % mod;
	if (mid < y)
		ans = (ll)ans * query(x, y, mid + 1, r, rs[p]) % mod;
	return ans;
}

int main() {
	int n = rd(), m = rd();
	for (int i = 1; i <= n; i ++ ) {
		a[i] = rd();
	}

	bfr[0] = 1;
	for (int i = 1; i <= n; i ++ ) {
		bfr[i] = (ll)bfr[i - 1] * a[i] % mod;
	}

	init();
	for (int i = 1; i <= cnt; i ++ ) {
		for (int j = prime[i]; j <= 1000000; j += prime[i]) {
			v[j].push_back(i);
		}
	}

	// cout << prime[cnt] << endl ;

	// for (int i = 1; i <= n; i ++ ) {
	// 	int len = v[a[i]].size();
	// 	for (int j = 0; j < len; j ++ ) {
	// 		printf("%d ",prime[v[a[i]][j]]);
	// 	}
	// 	puts("");
	// }

	sum[0] = 1;

	for (int i = 1; i <= n; i ++ ) {
		int len = v[a[i]].size();
		for (int j = 0; j < len; j ++ ) {
			if (pre[v[a[i]][j]]) {
				update(pre[v[a[i]][j]], (ll)prime[v[a[i]][j]] * qpow(prime[v[a[i]][j]] - 1, mod - 2) % mod, 1, n, (root[i] ? root[i] : root[i - 1]), root[i]);
			}
			update(i, (ll)(prime[v[a[i]][j]] - 1) * qpow(prime[v[a[i]][j]], mod - 2) % mod, 1, n, (root[i] ? root[i] : root[i - 1]), root[i]);
			// printf("Shit %d\n",v[a[i]][j]);
			pre[v[a[i]][j]] = i;
		}
	}

	// cout << sum[root[1]] << endl ;
	// cout << (ll)sum[root[1]] * 3 % mod * qpow(2, mod - 2) % mod << endl ;

	// cout << sum[root[4]] << endl ;
	// cout << (ll)sum[root[4]] * 2 * 6 * 4 % mod * qpow(3, mod - 2) % mod * qpow(2, mod - 2) % mod * qpow(5, mod - 2) % mod * qpow(7, mod - 2) % mod << endl ;

	// puts("Fuck");

	int lastans = 0;
	for (int i = 1; i <= m; i ++ ) {
		int x = rd(), y = rd();
		x ^= lastans, y ^= lastans;
		if (x > y) {
			lastans = 1;
			puts("0");
			continue;
		}
		// cout << (ll)bfr[y] * qpow(bfr[x - 1], mod - 2) % mod << endl ;
		lastans = (ll)bfr[y] * qpow(bfr[x - 1], mod - 2) % mod * query(x, y, 1, n, root[y]) % mod;
		printf("%d\n", lastans);
	}
	return 0;
}

Summary : Really good question ah, it is important that property can not be found. Chairman of the use of tree is also very clever.

Guess you like

Origin www.cnblogs.com/ShuraK/p/11255815.html