题解:炼石计划9 T1

题目链接

简述题意

求满足下面条件的集合个数:

  1. 集合元素 gcd 为 1
  2. 集合元素 lcm 为 n

\(n \in [1, 10^{14}]\)

分析

如果我对于 n 质因数分解为一下形式:

\[n = \prod_{i = 1} ^k p_i ^ {e_i} \]

那么我们一个可行的集合中,对每一个质因子都有这个:集合中数包含这个质因子的次数最大是 \(e_i\),最小是 0。

现在我们有两个限制,不是很好做,因为他是找一个满足一个,再找另一个满足另一个。

我们可以反过来,对于一个质因子,考虑其不满足的情况,即 【gcd 不为 0】 + 【lcm 不为 e】 - 【gcd 不为 0 且 lcm 不为 e】。

那我们上升到整个数,即所有质因子时应该怎么做呢?

如果不考虑限制,那么显然答案是二的质因子次数加一相乘。

那我们给他每个答案加上个容斥系数,枚举每个质因数的状态:

  1. 不限制,每个质因子可以取 \([0, e_i]\), \(e_i + 1\) 个数。
  2. gcd 不为 0 或 lcm 不为 e,\(e_i\) 个数。
  3. gcd 不为 0 且 lcm 不为 e,\(e_i - 1\) 个数。

最后加起来。

code

#include <bits/stdc++.h>
using namespace std;

const int Mod = 998244353;

typedef long long ll;

vector<int> q;

int qpow(ll a, ll b) {
	ll res = 1;
	while (b) {
		if (b & 1) {
			res *= a;
			res %= Mod;
		}
		a *= a;
		a %= Mod;
		b >>= 1;
	}
	return res;
}

int cnt = 0;
int ans = 0;
vector<int> p;
void dfs(int pos, int num, int k) {
	if (pos == cnt) {
		ans += 1ll * qpow(2, num) * k % Mod;
		ans %= Mod;
		return ;
	}
	dfs(pos + 1, num * (p[pos] + 1) % (Mod - 1), k);
	dfs(pos + 1, num * (p[pos] - 1) % (Mod - 1), k);
	dfs(pos + 1, num * p[pos] % (Mod - 1), -2 * k % Mod);
}

int main() {
	freopen("set.in", "r", stdin);
	freopen("set.out", "w", stdout);
	ll n;
	cin >> n;
	ll tn = n;
	
	for (int i = 2;i * i <= tn;i++) {
		if (tn % i) continue;
		int e = 0;
		while (tn % i == 0) {
			e++;
			tn /= i;
		}
		p.push_back(e);
	}
	if (tn > 1) {
		p.push_back(1);
	}
	
	cnt = p.size();
	dfs(0, 1, 1);
	
	ans = (ans + Mod) % Mod;
	cout << ans;
	
	return 0;
} 
posted @ 2025-10-01 16:43  yanbinmu  阅读(9)  评论(0)    收藏  举报