Examples

2022-8-5 #22 CF653G

前几天都在摆啊,不知不觉就到了 UNR 了。

056 CF653G Move by Prime

容易发现质数之间互不影响,不妨令序列中质数对应幂次分别为 \(x_1,x_2,\cdots,x_n\),我们只需将所有 \(x\) 调整至中位数,考虑每个点的贡献即:排名在严格前一半产生负贡献,排名在严格后一半产生正贡献。

对于排名为 \(i\) 的值,列出式子:

\[F(x)=(1+\frac{1}{x})^{i-1}(1+x)^{n-i}=\frac{(1+x)^{n-1}}{x^{i-1}} \]

即提取 \(F\) 正次数系数减去负次数系数,得到:

\[\sum_i x_i(\sum_{j=i}^{n-1}{n-1\choose j}-\sum_{j=0}^{i-2}{n-1\choose j}) \]

直接计算即可,复杂度 \(O(n\log n)\)

做个前缀和,利用埃氏筛可以做到 \(O(n\log \log n)\)


#include<stdio.h>
const int maxn=300005,mod=1000000007;
int n,ps,ans;
int a[maxn],p[maxn],c[maxn],fac[maxn],nfac[maxn],inv[maxn],sum[maxn],v[maxn],tot[maxn],cnt[maxn];
void sieve(int n){
	c[1]=fac[0]=fac[1]=nfac[0]=nfac[1]=inv[1]=1;
	for(int i=2;i<=n;i++){
		fac[i]=1ll*fac[i-1]*i%mod,inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod,nfac[i]=1ll*nfac[i-1]*inv[i]%mod;
		if(c[i]==0)
			p[++ps]=i;
		for(int j=1;j<=ps&&i*p[j]<=n;j++){
			c[i*p[j]]=1;
			if(i%p[j]==0)
				break;
		}
	}
}
inline int C(int a,int b){
	return a<b? 0:1ll*fac[a]*nfac[b]%mod*nfac[a-b]%mod;
}
int main(){
	sieve(300000),scanf("%d",&n);
	for(int i=1,x;i<=n;i++)
		scanf("%d",&x),tot[x]++;
	sum[0]=1;
	for(int i=1;i<n;i++)
		sum[i]=(sum[i-1]+C(n-1,i))%mod;
	for(int i=1;i<=n;i++)
		v[i]=(0ll+v[i-1]+sum[n-1]-sum[i-1]-(i>=2? sum[i-2]:0)+mod+mod)%mod;
	for(int i=1;i<=ps;i++){
		int x=p[i],mul=x,c=0;
		while(1){
			c++,cnt[c]=0;
			for(int j=mul;j<=300000;j+=mul)
				cnt[c]+=tot[j];
			if(cnt[c]==0){
				c--;
				break;
			}
			if(1ll*mul*x>300000)
				break;
			mul*=x;
		}
		cnt[c+1]=0;
		for(int j=1;j<=c;j++)
			ans=(ans+1ll*(v[cnt[j]]-v[cnt[j+1]])*j)%mod;
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2022-08-05 20:08  xiaoziyao  阅读(44)  评论(0编辑  收藏  举报