关于约数个数上界
查看原帖
关于约数个数上界
131591
蒟蒻君HJT泽渡透香楼主2023/2/8 22:21

查表可得约数个数上界为 13441344,但当 N=1789N=1789 时会 RE,改成 N=17890N=17890 才 AC,为什么呢

#include <bits/stdc++.h>
const int mod = 1e9 + 7;
inline int mul(int x, int y){
	return (int)(1ll * x * y % (1ll * mod));
}
inline int add(int x, int y){
	return x + y >= mod ? x + y - mod : x + y;
}
inline int minus(int x, int y){
	return x < y ? x - y + mod : x - y;
}
inline int Qpow(int x, int y){
	int r = 1;
	while(y){
		if(y & 1) r = mul(r, x);
		x = mul(x, x);
		y >>= 1;
	}
	return r;
}
inline int read(){
	char c = getchar();
	int x = 0;
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x;
}
const int N = 17890;
int f[N], g[N], h[N], t[N], k[N];
int n, q, P, v[1000005], cntp = 0, cc[123], p[123], pw2[1000005];
int Div[N], cntd = 0;
int gcd(int x, int y){
	return x % y == 0 ? y : gcd(y, x % y);
}
void dfs(int x, int y){
	if(x == cntp + 1) return Div[++cntd] = y, (void)0;
	int cury = y;
	for(int i = 0; i <= cc[x]; ++i) dfs(x + 1, cury), cury *= p[x];
	return ;
}
int find_(int x){
	int l = 1, r = cntd;
	while(l < r){
		int mid = l + r >> 1;
		if(Div[mid] == x) return mid;
		if(Div[mid] < x) l = mid + 1;
		else r = mid - 1;
	}
	return l;
}
void solve(){
	scanf("%d%d%d", &n, &q, &P); int PP = P;
	for(int i = 1; i <= n; ++i) v[i] = read();
	for(int i = 2; i * i <= P; ++i)
		if(PP % i == 0){
			++cntp; p[cntp] = i;
			while(PP % i == 0) PP /= i, ++cc[cntp];
		}
	if(PP) p[++cntp] = PP, cc[cntp] = 1;
	dfs(1, 1);
	std::sort(Div + 1, Div + cntd + 1);
	//for(int i = 1; i <= cntd; ++i) printf("%d ", Div[i]);
	//printf("\n");
	for(int i = 1; i <= n; ++i) ++t[find_(gcd(v[i], P))];
	//for(int i = 1; i <= cntd; ++i) printf("t[%d] = %d\n", i, t[i]);
	for(int i = 1; i <= cntd; ++i)
		for(int j = 1; j <= cntd; ++j)
			if(Div[j] % Div[i] == 0)
				h[i] += t[j];
	//for(int i = 1; i <= cntd; ++i) printf("h[%d] = %d\n", i, h[i]);
	pw2[0] = 1;
	for(int i = 1; i <= n; ++i) pw2[i] = mul(2, pw2[i - 1]);
	for(int i = 1; i <= cntd; ++i) g[i] = pw2[h[i]];
	for(int i = cntd; i >= 1; --i){
		f[i] = g[i];
		for(int j = 1; j <= cntd; ++j)
			if(Div[j] % Div[i] == 0 && i != j)
				f[i] = minus(f[i], f[j]);
	}			
	for(int i = 1; i <= cntd; ++i)
		for(int j = 1; j <= cntd; ++j)
			if(Div[i] % Div[j] == 0)
				k[i] = add(k[i], f[j]);
	for(int i = 1; i <= q; ++i) printf("%d\n", k[find_(gcd(P, read()))]);
	return ;
}
int main(){
	int T = 1;
	while(T--) solve();
	return 0;
}


2023/2/8 22:21
加载中...