阿狸有一个可重集合(A),(A)中有(n)个元素,因此(A)有(2n)个子集。对于每个(A)的子集(x),定义(f(x))的值为,使(x)的所有元素都相同的最少操作步数。操作有两种:
-
选择(x)中的一个元素,把这个数乘上某个质数(p)。
-
选择(x)中的一个元素,把这个数除掉某个质数(p)。这个数必须是(p)的倍数。
阿狸想知道(sumlimits_{xsubset A}f(x))的值,但是由于这个值可能很大,你只要告诉萌萌的阿狸这个数对(1,000,000,007(10^9+7))取模的值。
前置知识
上指标求和公式
[sum_{k=x}^ninom{k}{x}=inom{n+1}{x+1}
]
由数学归纳法易得。
范德蒙德卷积公式
[sum_{k=0}^sinom{n}{k}inom{m}{m-k}=inom{n+m}{s}
]
考虑生成函数,(inom{n}{k})的生成函数为((1+x)^n),左侧很明显是一个卷积,则右侧的生成函数为((1+x)^{n+m}),易证。
由对称性,得:
[sum_{k=0}^ninom{n}{k}inom{m}{k}=inom{n+m}{n}
]
解决
显然,不同质因数之间可以分开处理。考虑对于一个质因子,求出这(n)个数中这个质因子的幂次,并排序,得到序列(a)。
容易发现,问题就是要求
[minleft{sum_{k=1}^nleft|x-a_k
ight|
ight}
]
显然,取中位数为最佳。换言之,从最左和最右的两个数开始,依次向内配对。
考虑所有子集中每一个点对的贡献:两侧所取的数的个数必须相等,中间的数可以任意取。则有:
[egin{align*}
S&=sum_{i=1}^nsum_{j=i}^n(a_j-a_i)2^{j-i-1}sum_{k=0}^ninom{i-1}{k}inom{n-j}{k}\
&=sum_{i=1}^nsum_{j=i}^n(a_j-a_i)2^{j-1-1}inom{i-1+n-j}{i-1}
end{align*}
]
改为枚举(s=i-1+n-j),有:
[egin{align*}
S&=sum_{s=0}^{n-1}sum_{i=0}^s(a_{n-s+i}-a_{i+1})2^{n-s-2}inom{s}{i}\
end{align*}
]
减号两侧分开处理。
左侧
[egin{align*}
S_0&=sum_{s=0}^{n-1}sum_{i=0}^sa_{n-s+i}2^{n-s-2}inom{s}{i}\
&=sum_{s=0}^{n-1}sum_{i=0}^sa_{n-i}2^{n-s-2}inom{s}{i}\
&=sum_{i=0}^{n-1}a_{n-i}sum_{s=i}^{n-1}2^{n-s-2}inom{s}{i}\
&=sum_{i=1}^{n}a_{i}sum_{s=n-i}^{n-1}2^{n-s-2}inom{s}{n-i}\
&=sum_{i=1}^{n}a_{i}sum_{s=1}^{i}2^{s-2}inom{n-s}{n-i}\
end{align*}
]
记
[f_x=sum_{s=1}^{n-x}2^{s-2}inom{n-s}{x}
]
则
[S_0=sum_{i=1}^na_if_{n-i}
]
右侧
[egin{align*}
S_1&=sum_{s=0}^{n-1}sum_{i=0}^sa_{i+1}2^{n-s-2}inom{s}{i}\
&=sum_{i=0}^{n-1}a_{i+1}sum_{s=i}^{n-1}2^{n-s-2}inom{s}{i}\
&=sum_{i=1}^{n}a_isum_{s=i-1}^{n-1}2^{n-s-2}inom{s}{i-1}\
&=sum_{i=1}^na_isum_{s=1}^{n-i+1}2^{s-2}inom{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)) |
则有
[egin{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*}
]
一般性的,有:
[egin{align*}
f_k&=f_{k-1}-frac{1}{2}sum_{x=k-1}^{n-1}inom{x}{k-1}\
&=f_{k-1}-frac{1}{2}inom{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
",ans);
}