[Ynoi2015] 此时此刻的光辉

[Ynoi2015] 此时此刻的光辉

买了新的草稿纸,所以来水一下这题。

挺简单的,直接Pollard-Rho质因数分解之后莫队就行了。

但是为了卡常可以用一个小trick,把比较小的质因子用处理了,这样子莫队和Pollard-Rho都会快一些。

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
template <typename T>
inline void read(T &x) {
	x = 0; int f = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
	for(; isdigit(ch); ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
	if(f) x = ~x + 1;
}
const int B = 1000;
int vis[B + 10], p[B + 10], totB;
void Sieve() {
	for(int i = 2; i <= B; ++i) {
		if(!vis[i]) p[++totB] = i;
		for(int j = 1; j <=totB && i * p[j] <= B; ++j) {
			vis[i * p[j]] = 1;
			if(i % p[j] == 0) break;
		}
	}
}
using LL = long long;
using ull = unsigned long long;
using vi = vector<int>;
ull mul(ull x, ull y, ull P) {
	LL res = x * y - P * ull(1.L / P * x * y);
	return res + P * (res < 0) - P * (res >= (LL)P);
}
ull fpow(ull x, ull pnt, ull P) {
	if(x >= P) x %= P;
	ull res = 1;
	for(; pnt; pnt >>= 1, x = mul(x, x, P)) 
		if(pnt & 1) res = mul(res, x, P);
	return res;
} 
const ull A[] = {2,325,9375,28178,450775,9780504,1795265022}; 
bool isPrime(ull n) {
	if(n < 3 || !(n & 1)) return n == 2;
	ull s = __builtin_ctzll(n - 1), t = n >> s;
	for(ull a : A) {
		ull p = fpow(a, t, n), i = s;
		while(p != 1 && p != n - 1 && a % n && i--) 
			p = mul(p, p, n);
		if(p != n - 1 && i != s) return false;
	}
	return true;
}
int pollard(ull n) {
	auto f = [n](ull x) {return mul(x, x, n) + 1;};
	ull x = 0, y = 0, t = 30, prd = 2, i = 1, q;
	while(t++ % 40 || __gcd(prd, n) == 1) {
		if(x == y) x = ++i, y = f(x);
		if((q = mul(prd, max(x, y) - min(x, y), n))) prd = q;
		x = f(x), y = f(f(y));
	}
	return __gcd(prd, n);
}
vi factor(int n) {
	if(n == 1) return {};
	if(isPrime(n)) return {n};
	int x = pollard(n);
	auto l = factor(x), r = factor(n / x);
	for(auto x : r) l.emplace_back(x);
	return l;
}
const int N = 1e5 + 10;
struct Query {
	int l, r, id;
}q[N];
const int QB = 384;
bool cmp(Query x, Query y) {
	return ((x.l / QB) == (y.l / QB)) ? 
		   (((x.l / QB) & 1) ? (x.r < y.r) : (x.r > y.r)) :
		   (x.l < y.l);
}
const LL P = 19260817;
LL inv[N * 32], cur = 1;
int tot;
unordered_map<int, int> id;
vector<int> fac[N];
int buc[N << 2];
inline void add(int x) {
	for(auto p : fac[x]) {
		cur = cur * inv[buc[p] + 1] % P;
		++buc[p];
		cur = cur * (buc[p] + 1) % P;
	}
}
inline void del(int x) {
	for(auto p : fac[x]) {
		cur = cur * inv[buc[p] + 1] % P;
		--buc[p];
		cur = cur * (buc[p] + 1) % P;
	}
}
int n, m, a[N], cnt[N][200], ans[N];
int main() {
	Sieve();
	read(n), read(m);
	inv[1] = 1;
	for(int i = 2; i <= n * 32; ++i) inv[i] = (P - P / i) * inv[P % i] % P;
	for(int i = 1; i <= n; ++i) {
		read(a[i]);
		int tmp = a[i]; 
		for(int j = 1; j <= totB; ++j) {
			cnt[i][j] = cnt[i - 1][j];
			while(tmp % p[j] == 0) ++cnt[i][j], tmp /= p[j];
		}
		fac[i] = factor(tmp);
		for(auto &x : fac[i]) {
			auto &p = id[x];
			if(!p) p = ++tot;
			x = p;
		}
	}
	for(int i = 1; i <= m; ++i) read(q[i].l), read(q[i].r), q[i].id = i;
	sort(q + 1, q + m + 1, cmp);
	for(int l = 1, r = 0, i = 1; i <= m; ++i) {
		while(r < q[i].r) add(++r);
		while(l > q[i].l) add(--l);
		while(r > q[i].r) del(r--);
		while(l < q[i].l) del(l++);
		LL tmp = cur;
		for(int j = 1; j <= totB; ++j)
			tmp = tmp * (cnt[q[i].r][j] - cnt[q[i].l - 1][j] + 1) % P;
		ans[q[i].id] = tmp;
	}
	for(int i = 1; i <= m; ++i) printf("%d\n",ans[i]);
}
posted @ 2022-11-15 15:06  DCH233  阅读(23)  评论(0编辑  收藏  举报