蒟蒻TJY的博客

一道综合数学题

阿狸有一个可重集合\(A\)\(A\)中有\(n\)个元素,因此\(A\)\(2n\)个子集。对于每个\(A\)的子集\(x\),定义\(f(x)\)的值为,使\(x\)的所有元素都相同的最少操作步数。操作有两种:

  • 选择\(x\)中的一个元素,把这个数乘上某个质数\(p\)

  • 选择\(x\)中的一个元素,把这个数除掉某个质数\(p\)。这个数必须是\(p\)的倍数。

阿狸想知道\(\sum\limits_{x\subset A}f(x)\)的值,但是由于这个值可能很大,你只要告诉萌萌的阿狸这个数对\(1,000,000,007(10^9+7)\)取模的值。

前置知识

上指标求和公式

\[\sum_{k=x}^n\binom{k}{x}=\binom{n+1}{x+1} \]

由数学归纳法易得。

范德蒙德卷积公式

\[\sum_{k=0}^s\binom{n}{k}\binom{m}{m-k}=\binom{n+m}{s} \]

考虑生成函数,\(\binom{n}{k}\)的生成函数为\((1+x)^n\),左侧很明显是一个卷积,则右侧的生成函数为\((1+x)^{n+m}\),易证。

由对称性,得:

\[\sum_{k=0}^n\binom{n}{k}\binom{m}{k}=\binom{n+m}{n} \]

解决

显然,不同质因数之间可以分开处理。考虑对于一个质因子,求出这\(n\)个数中这个质因子的幂次,并排序,得到序列\(a\)

容易发现,问题就是要求

\[\min\left\{\sum_{k=1}^n\left|x-a_k\right|\right\} \]

显然,取中位数为最佳。换言之,从最左和最右的两个数开始,依次向内配对。

考虑所有子集中每一个点对的贡献:两侧所取的数的个数必须相等,中间的数可以任意取。则有:

\[\begin{align*} S&=\sum_{i=1}^n\sum_{j=i}^n(a_j-a_i)2^{j-i-1}\sum_{k=0}^n\binom{i-1}{k}\binom{n-j}{k}\\ &=\sum_{i=1}^n\sum_{j=i}^n(a_j-a_i)2^{j-1-1}\binom{i-1+n-j}{i-1} \end{align*} \]

改为枚举\(s=i-1+n-j\),有:

\[\begin{align*} S&=\sum_{s=0}^{n-1}\sum_{i=0}^s(a_{n-s+i}-a_{i+1})2^{n-s-2}\binom{s}{i}\\ \end{align*} \]

减号两侧分开处理。

左侧

\[\begin{align*} S_0&=\sum_{s=0}^{n-1}\sum_{i=0}^sa_{n-s+i}2^{n-s-2}\binom{s}{i}\\ &=\sum_{s=0}^{n-1}\sum_{i=0}^sa_{n-i}2^{n-s-2}\binom{s}{i}\\ &=\sum_{i=0}^{n-1}a_{n-i}\sum_{s=i}^{n-1}2^{n-s-2}\binom{s}{i}\\ &=\sum_{i=1}^{n}a_{i}\sum_{s=n-i}^{n-1}2^{n-s-2}\binom{s}{n-i}\\ &=\sum_{i=1}^{n}a_{i}\sum_{s=1}^{i}2^{s-2}\binom{n-s}{n-i}\\ \end{align*} \]

\[f_x=\sum_{s=1}^{n-x}2^{s-2}\binom{n-s}{x} \]

\[S_0=\sum_{i=1}^na_if_{n-i} \]

右侧

\[\begin{align*} S_1&=\sum_{s=0}^{n-1}\sum_{i=0}^sa_{i+1}2^{n-s-2}\binom{s}{i}\\ &=\sum_{i=0}^{n-1}a_{i+1}\sum_{s=i}^{n-1}2^{n-s-2}\binom{s}{i}\\ &=\sum_{i=1}^{n}a_i\sum_{s=i-1}^{n-1}2^{n-s-2}\binom{s}{i-1}\\ &=\sum_{i=1}^na_i\sum_{s=1}^{n-i+1}2^{s-2}\binom{n-s}{i-1}\\ &=\sum_{i=1}^na_if_{i-1} \end{align*} \]

合并

\[S=S_0-S_1=\sum_{i=1}^na_i(f_{n-i}-f_{i-1}) \]

问题就转化成如何求\(f_i\)

显然,这个问题没有简单的形式可以找寻。不妨观察其形式,在Pascal三角形上观察,可以尝试找出一个递归式。

考虑一个局部:

\(f_0\) \(f_1\)
\(4a\)
\(2b\) \(2a\)
\(c\) \(a+b\)
\(\frac{1}{2}d\) \(\frac{1}{2}(a+b+c)\)

则有

\[\begin{align*} f_0&=4a+2b+c+\frac{1}{2}d\\ f_1&=2a+(a+b)+\frac{1}{2}(a+b+c)\\ &=(2+1+\frac{1}{2})a+(1+\frac{1}{2})b+\frac{1}{2}c\\ &=f_0-\frac{1}{2}(a+b+c+d) \end{align*} \]

一般性的,有:

\[\begin{align*} f_k&=f_{k-1}-\frac{1}{2}\sum_{x=k-1}^{n-1}\binom{x}{k-1}\\ &=f_{k-1}-\frac{1}{2}\binom{n}{k} \end{align*} \]

这就可以\(O(n)\)求了。至此,问题解决。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7,inv2=5e8+4;
const int N=300001;
int n,cnt,cx,pri[N],e[N];
bool cm[N];
ll ans,fcn,inv[N],ifc[N],c[N];
vector<int>num[N];
char buf[N*10];
inline ll add(ll a,ll b){return a+b>=mod?a+b-mod:a+b;}
inline ll cut(ll a,ll b){return a-b<0?a-b+mod:a-b;}
inline ll mul(ll a,ll b){return a*b%mod;}
ll fpow(ll a,ll b){ll bs=1;while(b){if(b&1)bs=mul(bs,a);a=mul(a,a);b>>=1;}return bs;}
inline ll C(int k){return mul(fcn,mul(ifc[k],ifc[n-k]));}
void init(){
	for(int i=2;i<N;i++){
		if(!cm[i]){pri[++cnt]=i;e[i]=cnt;}
		for(int j=1;j<=cnt&&i*pri[j]<N;j++){
			cm[i*pri[j]]=true;
			e[i*pri[j]]=j;
			if(i%pri[j]==0)break;
		}
	}
	fcn=inv[1]=ifc[0]=1;
	for(int i=1;i<=n;i++)fcn=mul(fcn,i);
	for(int i=2;i<=n;i++)inv[i]=mul(mod-mod/i,inv[mod%i]);
	for(int i=1;i<=n;i++)ifc[i]=mul(ifc[i-1],inv[i]);
	c[0]=mul(cut(fpow(2,n),1),inv2);
	for(int i=1;i<n;i++)c[i]=cut(c[i-1],mul(C(i),inv2));
}
inline ll f(int k){return cut(c[n-k],c[k-1]);}
inline int rd(){
	int s=0;
	while(buf[cx]<'0'||buf[cx]>'9')++cx;
	while('0'<=buf[cx]&&buf[cx]<='9')s=10*s+buf[cx++]-'0';
	return s;
}
int main(){
	fread(buf,sizeof(char),N*10,stdin);
	n=rd();
	init();
	for(int i=1;i<=n;i++){
		int a=rd();
		while(a>1){
			int x=e[a],s=0;
			while(a%pri[x]==0){a/=pri[x];s++;}
			num[x].push_back(s);
		}
	}
	for(int i=1;i<=cnt;i++){
		int s=num[i].size();
		sort(num[i].begin(),num[i].end());
		for(int j=0;j<s;j++)ans=add(ans,mul(num[i][j],f(n-s+j+1)));
	}
	printf("%lld\n",ans);
}
posted @ 2020-10-23 13:16  蒟蒻TJY  阅读(136)  评论(0编辑  收藏  举报