# [Gym101138G][容斥原理]LCM-er

## 题意描述

${a \le A_1 \le A_2 \le A_3 \le A_4 \le \cdots \le A_n \le b }\\ 1 \le n\le 100,1\le a,b,x \le 10^9, a\le b \\$

${lcm(A_1,A_2,A_3,\cdots ,A_n) | x}$

## 解法解析

\begin{aligned} x &= p_1^{k_1}p_2^{k_2}\cdots p_m^{k_m} \\ lcm &= p_1^{t_1}p_2^{t_2}\cdots p_m^{t_m} \\ \end{aligned} \\ 需要满足\ k_i \le t_i (1\le i\le m)

$q_i代表第i个位置合法的情况, S代表所有位置的集合\{1,2,3,\cdots,m\},F代表满足指定情况下的方案数​$

\begin{aligned} F\left(\bigcap_{i=1}^m q_i \right) &= {All - F\left(\bigcup_{i=1}^m\overline{q_i} \right)} \\ F\left(\bigcup_{i=1}^m\overline{q_i} \right) &= {F(\overline{q_1})+F(\overline{q_2})+\cdots+F(\overline{q_m})} \\ &{-\sum_{1\le i\lt j\le m}F(\overline{q_i}\cap\overline{q_j})} \\ &{+\sum_{1\le i\lt j\lt k\le m}F(\overline{q_i}\cap\overline{q_j}\cap\overline{q_j})} \\ &\cdots \\ &{+\sum_{t\subseteq S}(-1)^{|t|}F\left( \bigcap_{i\in t}\overline{q_i}\ \right)} \end{aligned}

$G(q_i)代表[a,b]区间内不为对应i位置质数幂倍数的数字数\\ {G\left( \bigcap_{i\in t}\overline{q_i}\ \right) =(b-a+1)+\sum_{j\subseteq t}(-1)^{|j|}\left( \Big\lfloor \frac{b}{\prod_{x\in j}p_x^{k_x}}\Big\rfloor - \Big\lfloor \frac{a-1}{\prod_{x\in j}p_x^{k_x}}\Big\rfloor \right)}$

${F\left( \bigcap_{i\in t}\overline{q_i}\ \right) = \binom{G\left( \bigcap_{i\in t}\overline{q_i}\ \right)+n-1}{n}}$

PS:代码写得异常奇怪，就想试试不开数组只用vector

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

const int MOD = 1e9 + 7;
const int BIT = 11;
const int N = 105;
vector<int> inv(N, 1);

void init_inverse() {
for (int i = 2; i < inv.size(); i++) {
inv[i] = 1LL * (MOD - MOD / i) * inv[MOD % i] % MOD;
}
}

void resolve(int x, vector<int>& factors) {
for (int i = 2; i * i <= x; i++) {
if (x % i == 0) {
factors.push_back(i);
x /= i;
while (x % i == 0) {
*factors.rbegin() *= i;
x /= i;
}
}
}
if (x > 1) factors.push_back(x);
}

int calc(int x, int l, int r) {
return r / x - (l - 1) / x;
}

int comb(int n, int m) {
if (m > n || m < 0) return 0;
int ret = 1;
for (int i = 1; i <= m; i++) {
ret = 1LL * ret * inv[i] % MOD;
ret = 1LL * ret * (n - i + 1) % MOD;
}
return ret;
}

int main() {
init_inverse();

int n, a, b, x;
vector<int> factors;

cin >> n >> a >> b >> x;
resolve(x, factors);

vector<int> lcm(1 << factors.size(), 1);
vector<int> weight(1 << factors.size(), 0);
vector<int> cnt(1 << factors.size(), 0);

for (int i = 0, j = 1; j < weight.size(); i++, j = j + j) {
weight[j] = i;
}
for (int i = 1; i < lcm.size(); i++) {
lcm[i] = lcm[i - (i & -i)] * factors[weight[i & -i]];
cnt[i] = cnt[i - (i & -i)] + 1;
}

int ans = 0;
for (int i = 0; i < lcm.size(); i++) {
int temp = b - a + 1;
for (int j = i; j; j = i & (j - 1)) {
if (cnt[j] & 1) {
temp = (temp - calc(lcm[j], a, b) + MOD) % MOD;
} else {
temp = (temp + calc(lcm[j], a, b)) % MOD;
}
}
if (cnt[i] & 1) {
ans = (ans - comb(temp + n - 1, n) + MOD) % MOD;
} else {
ans = (ans + comb(temp + n - 1, n)) % MOD;
}
}
cout << ans << endl;

return 0;
}
posted @ 2019-04-05 00:28  UnderSilence  阅读(...)  评论(...编辑  收藏