abc423 F - Loud Cicada
F - Loud Cicada
题意
给你 \(n\) 个数 \(a_i\),问有多少个 \(x \in [1,Y]\) 满足 \(a_i \mid x\) 的 \(i\) 的个数等于 \(m\)。
\(n ,m \le 20, a_i,Y \le 10^{18}\)。
思路
\(a_i \mid x\) 的 \(x\) 有 \(\lfloor \frac{Y}{a_i} \rfloor\) 个。
显然可以枚举 \(i\) 的集合 \(S\),然后计算 \(\lfloor \frac{Y}{\text{lcm}(a_i ,i\in S)} \rfloor\)。
然后算容斥系数。
容斥系数可以手推出来:
设 \(f_k\) 表示 \(|S| = k\) 的容斥系数。
假设 \(m=2\)。
\(f_2 = 1\)。
\(|S|=3\) 的方案应该总共被计算 \(0\) 次,现在已经被计算了 \(\binom{3}{2}\) 次,所以 \(f_3 = - \binom{3}{2}\)。
\(|S|=4\) 的方案应该总共被计算 \(0\) 次,现在已经被计算了 \(\binom{4}{2} - \binom{3}{2} \binom{4}{3}\) 次,所以 \(f_4 = -\binom{4}{2} + \binom{3}{2} \binom{4}{3}\)。
即 \(f_m=1, f_k = - \sum_{i=m}^{k-1} \binom{k}{i} f_i\)。
于是就可以 \(O(2^n n + n^2)\) 做了。
注意,本段全是废话:
什么广义容斥原理、什么莫比乌斯变换,我完全看不懂啊,原来的定理如何证明和怎么运用到这题都不懂,有空必须学习一下,数学实在是太差了。
注意一些爆 long long 的问题。甚至会爆 __int128。我的解决方法是计算过程对一个大质数取模,因为最终答案显然 \(< Y\),所以是正确的吧(?。
注意上面这个是错的。
但是亲爱的,你告诉我,只 WA 一个 01-02.txt 是什么意思?
似乎在学术版看到了和我一样的做法。为啥直接用 __int128 是对的啊?
反正能过,就直接用 __int128 吧。
大神们都说这是二项式反演,我苦思冥想不能理解。那么我们使用二项式反演推一推。
唉,AI 还是太强了,就是理解能力有点奇怪。
设 \(f_k\) 表示恰好有 \(i\) 个 \(a_i\),\(a_i\mid x\) 的 \(x\) 的个数。
答案就是 \(f_m\)。
但是 \(f_k\) 不好求。
设 \(g_k\) 表示满足至少有 \(k\) 个 \(a_i\),\(a_i \mid x\) 的 \(x\) 的个数。
但是 \(g_k\) 也不好求。
设 \(h_k = \sum_{|S| = k} \lfloor \frac{Y}{\text{lcm}(a_i ,i\in S)} \rfloor\)。考虑 \(h_k\) 算重了多少。
一个有 \(c\) 个 \(a_i \mid x\) 的 \(x\) 会被算 \(\binom{c}{k}\) 次。
所以:
然后根据二项式反演,有;
证明二项式反演:
感谢 @CuteNess 的帮助!
\(F_S\) 表示恰好 \(i \in S, a_i \mid x\) 的 \(x\) 的个数。
\(G_S\) 表示 \(\forall i \in S, a_i \mid x\) 的 \(x\) 的个数。\(G_S = \lfloor \frac{Y}{\text{lcm}(a_i ,i\in S)} \rfloor\)。
那么 \(G_S = \sum_{S \subseteq T} F_T\)。
然后子集反演,得到 \(F_S = \sum_{S \subseteq T} (-1)^{|T|-|S|} G_T\)。
\(h_j = \sum_{|S| = j} G_S\)。
一个大小为 \(j\) 的 \(T\) 就会被 \(\binom{j}{k}\) 个 \(S\) 算到。
所以 \(f_k = \sum_{j \ge k} (-1)^{j-k} G_T\)。
AI 的证明,太丑陋了!
理解二项式反演的推导,最好从「具体例子」入手,先观察规律,再上升到「组合恒等式」和「生成函数」的抽象证明。以下是分步推导思路,重点解释“为什么反演公式长这样”:
一、从具体例子找规律:n=2的情况
先看最简单的场景,设 \(n=2\),此时原关系式为:
我们的目标是从 \(h_i\) 反推 \(f_i\)。可以直接解方程组:
- 由 \(h_2 = f_2\),得 \(f_2 = h_2\);
 - 代入 \(h_1 = f_1 + 2f_2\),得 \(f_1 = h_1 - 2f_2 = h_1 - 2h_2\);
 - 代入 \(h_0 = f_0 + f_1 + f_2\),得 \(f_0 = h_0 - f_1 - f_2 = h_0 - (h_1 - 2h_2) - h_2 = h_0 - h_1 + h_2\)。
 
观察结果,发现规律:
每一项的系数都是 \((-1)^{j-i}\binom{j}{i}\)(例如 \(f_0\) 中 \(h_2\) 的系数是 \((-1)^{2-0}\binom{2}{0}=1\))。
二、n=3验证:规律是否一致?
原关系式:
解方程组:
- \(f_3 = h_3\);
 - \(f_2 = h_2 - 3f_3 = h_2 - 3h_3\);
 - \(f_1 = h_1 - 2f_2 - 3f_3 = h_1 - 2(h_2 - 3h_3) - 3h_3 = h_1 - 2h_2 + 3h_3\);
 - \(f_0 = h_0 - f_1 - f_2 - f_3 = h_0 - (h_1 - 2h_2 + 3h_3) - (h_2 - 3h_3) - h_3 = h_0 - h_1 + h_2 - h_3\)。
 
结果完全符合规律:
例如 \(f_1 = \binom{1}{1}h_1 - \binom{2}{1}h_2 + \binom{3}{1}h_3 = h_1 - 2h_2 + 3h_3\)。
三、核心问题:为什么是 \((-1)^{j-i}\binom{j}{i}\)?
从例子中可见,反演的关键是用交错符号(正负交替)抵消原关系式中“重复计算”的部分。
原关系式 \(h_i = \sum_{j≥i}\binom{j}{i}f_j\) 的本质是:\(f_j\) 会被所有 \(i≤j\) 的 \(h_i\) 计数 \(\binom{j}{i}\) 次(例如 \(f_3\) 在 \(h_1\) 中被计 \(\binom{3}{1}=3\) 次,在 \(h_2\) 中被计 \(\binom{3}{2}=3\) 次)。
反演需要“剥离”这些重复计数,而 \((-1)^{j-i}\) 的作用正是正负抵消:
- 当 \(j=i\) 时,只有 \(h_i\) 包含 \(f_i\),系数为正(\(\binom{i}{i}=1\));
 - 当 \(j>i\) 时,\(f_j\) 在 \(h_i\) 中被多计的部分,会被 \(h_{i+1},...,h_j\) 中的负系数抵消。
 
四、严格证明:利用组合恒等式
要证明对任意 \(i≤n\),有:
只需将原关系式 \(h_j = \sum_{k=j}^n \binom{k}{j}f_k\) 代入右边,验证结果等于 \(f_i\):
右边 \(= \sum_{j=i}^n (-1)^{j-i}\binom{j}{i} \cdot \sum_{k=j}^n \binom{k}{j}f_k\)
\(= \sum_{k=i}^n f_k \sum_{j=i}^k (-1)^{j-i}\binom{j}{i}\binom{k}{j}\) (交换求和顺序,\(k≥j≥i\))
核心是证明内层和 \(\sum_{j=i}^k (-1)^{j-i}\binom{j}{i}\binom{k}{j} = \delta_{i,k}\)(克罗内克符号:\(i=k\) 时为 1,否则为 0)。
化简内层和:
利用组合恒等式 \(\binom{j}{i}\binom{k}{j} = \binom{k}{i}\binom{k-i}{j-i}\)(从 \(k\) 中选 \(j\) 再选 \(i\),等价于先选 \(i\) 再从剩余 \(k-i\) 中选 \(j-i\))。
令 \(t = j - i\)(则 \(t≥0\),\(k-i≥t\)),内层和变为:
\(\sum_{t=0}^{k-i} (-1)^t \binom{k}{i}\binom{k-i}{t} = \binom{k}{i} \sum_{t=0}^{k-i} (-1)^t \binom{k-i}{t}\)
根据二项式定理,\(\sum_{t=0}^m (-1)^t \binom{m}{t} = (1-1)^m = 0^m\)(\(m≥1\) 时为 0,\(m=0\) 时为 1)。
因此:
- 当 \(k = i\) 时,\(m = k-i = 0\),和为 \(\binom{i}{i} \cdot 1 = 1\);
 - 当 \(k > i\) 时,\(m = k-i ≥1\),和为 \(\binom{k}{i} \cdot 0 = 0\)。
 
即内层和 \(= \delta_{i,k}\),因此右边 \(= \sum_{k=i}^n f_k \cdot \delta_{i,k} = f_i\),证明成立。
五、总结:理解反演的3个关键
- 直观来源:从低维例子(n=2,3)观察到反演系数的规律(交错符号+组合数);
 - 核心作用:\((-1)^{j-i}\) 抵消原关系式中 \(f_j\) 被重复计数的部分;
 - 严格基础:依赖组合恒等式 \(\sum_{t=0}^m (-1)^t \binom{m}{t} = 0^m\),这是二项式定理的直接结果。
 
结合计数问题(如“至少”与“恰好”的转换)理解会更深刻:反演本质是“修正重复计数”的数学工具。
code
#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
typedef __int128 lll;
namespace wing_heart {
	constexpr int N=21;
	int n,m;
	ll a[N],s;
	ll gcd(ll a,ll b) { return b ? gcd(b,a%b) : a; }
	ll getlcm(int t) {
		lll p=1;
		rep(i,1,n) if((t>>(i-1))&1) {
			p=(lll)p*a[i]/gcd(p,a[i]);
			if(p>s) return -1; 
		}
		return p;
	}
	lll ans;
	ll c[N][N];
    void main() {
		sf("%d%d%lld",&n,&m,&s);
		rep(i,1,n) sf("%lld",&a[i]);
		c[0][0]=1;
		rep(i,1,n) {
			c[i][0]=1;
			rep(j,1,i) c[i][j]=c[i-1][j-1]+c[i-1][j];
		}
		rep(i,1,(1<<n)-1) {
			int k=__builtin_popcount(i);
			if(k<m) continue;
			ll lcm=getlcm(i);
			if(lcm==-1) continue;
			ll op = (k-m)&1 ? -1 : 1;
			ans+=(lll)op*c[k][m]*(s/lcm);
		}
		pf("%lld\n",(ll)ans);
    }
}
int main() {
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("my.out","w",stdout);
    #endif
    wing_heart :: main();
}
本文来自博客园,作者:wing_heart,转载请注明原文链接:https://www.cnblogs.com/wingheart/p/19093140

                
            
        
浙公网安备 33010602011771号