zoukankan      html  css  js  c++  java
  • CF653G Move by Prime 题解

    Codeforces
    Luogu

    Description.

    定义 \(F(S)\) 为把 \(S\) 中每次可以把每个元素 \(\times p,\div p(p\in\text{prime})\) 把所有元素变相同的最少步数。
    \(\sum_{T\subseteq S}F(T)\)

    Solution.

    质因数可以拆开,分别求解
    对于每个质因数,有一个序列表示指数
    现在相当于对所有子序列求到中位数差之和
    可以考虑枚举中位数为 \(m\)(定义中位数偏左
    然后相当于要求 \(\sum|X-m|\) 其中 \(m\) 是中位数。
    绝对值拆开后,\(m\) 的贡献肯定是 \(0\)
    相当于在左边选 \(a\) 个,右边选 \(b\) 个的贡献是下式:

    \[\begin{cases} -X&a<b\\ 0&a=b\\ X&a>b\\ \end{cases} \]

    可以枚举 \(b-a+i-1\),意义是左边不选个数和右边选个数之和。
    因为 \(i\) 当前确定,左边不选、右边选总方案数就相当于从 \(n-1\) 里选出这些数,方案数是 \(\dbinom{n-1}{b-a+i-1}\)
    则有贡献为

    \[\begin{aligned} &=X\left(\sum_{j=0}^{i-2}\dbinom{n-1}{j}-\sum_{j=i}^{n-1}\dbinom{n-1}{j}\right)\\ &=X\left(2^{n-1}-2\sum_{j=i-1}^{n-1}\dbinom{n-1}{j}+\dbinom{n-1}{i}\right)\\ \end{aligned} \]

    然后预处理组合数前缀和就做完了。

    Coding.

    点击查看代码
    //Coded by Kamiyama_Shiki on 2021.11.14 {{{
    //是啊……你就是那只鬼了……所以被你碰到以后,就轮到我变成鬼了
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    const int N=300005,P=1000000007;
    namespace Binom//{{{
    {
    	int fc[N],fi[N],iv[N];//dbinit
    	inline int ksm(int x,int q=P-2) {int r=1;for(;q;q>>=1,x=1ll*x*x%P) if(q&1) r=1ll*r*x%P;return r;}
    	inline void dbinit(int n=N-1)
    	{
    		fc[0]=1;for(int i=1;i<=n;i++) fc[i]=1ll*fc[i-1]*i%P;
    		iv[1]=1;for(int i=2;i<=n;i++) iv[i]=1ll*iv[P%i]*(P-P/i)%P;
    		fi[0]=1;for(int i=1;i<=n;i++) fi[i]=1ll*fi[i-1]*iv[i]%P;
    	}
    	inline int C(int n,int m) {return n<0||m<0||n<m?0:1ll*fc[n]*fi[m]%P*fi[n-m]%P;}
    }using Binom::dbinit;using Binom::C;using Binom::ksm;//}}}
    const int V=N;int pr[V],pc,ls[V];char pv[V];//prinit{{{
    inline void prinit(int n=V-1)
    {
    	pv[1]=1,ls[1]=0;for(int i=1;i<=n;i++)
    	{
    		if(!pv[i]) pr[++pc]=i,ls[i]=i;
    		for(int j=1;j<=pc&&i*pr[j]<=n;j++) {pv[i*pr[j]]=1,ls[i*pr[j]]=pr[j];if(i%pr[j]==0) break;}
    	}
    }//}}}
    int n,a[N],c[N],qz[N],rs=0;vector<int>fc[N];
    int main()
    {
    	read(n),prinit(),dbinit();for(int i=1;i<=n;i++) read(a[i]);
    	int pw=ksm(2,n-1);for(int i=n-1;~i;i--) qz[i]=(qz[i+1]+(c[i]=C(n-1,i)))%P;
    	for(int i=1,x=a[i];i<=n;x=a[++i]) while(ls[x]) {int v=ls[x],c=0;while(x%v==0) x/=v,c++;fc[v].push_back(c);}
    	for(int i=1;i<N;i++) if(!fc[i].empty())
    	{
    		sort(fc[i].begin(),fc[i].end());int cnt=n-fc[i].size();
    		//printf("%d\n",i);for(int j:fc[i]) printf("%d ",j);putchar('\n');
    		for(int j=0;j<(int)fc[i].size();j++) rs=(rs+1ll*fc[i][j]*(pw-2ll*qz[cnt+j]%P+P+c[cnt+j]))%P;
    		//for(int j=0;j<(int)fc[i].size();j++) printf("gg %d - %lld + %d\n",pw,2ll*qz[cnt+j]%P,c[cnt+j]);
    	}return printf("%d\n",rs),0;
    }
    
  • 相关阅读:
    python 计算 父亲节
    python 计算 母亲节
    python 计算 感恩节
    《AINLP年度阅读收藏清单》,2020-01-01,52nlp
    《命名实体识别 NER 论文综述:那些年,我们一起追过的却仍未知道的花名 (一)》,2020-05,龚俊民(昵称: 除夕)
    《How to Automate Manual Steps after SSH》2019-03,amitness
    《Back Translation for Text Augmentation with Google Sheets》,2020-02,amitness
    《BERT 的优秀变体:ALBERT 论文图解介绍》2020-05,作者:amitness,译者:ronghuaiyang
    《NLP中数据增强的综述,快速的生成大量的训练数据》2020-05,作者:amitness ,编译:ronghuaiyang
    《努力成为优秀的工程师》李航,2013-03
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15553166.html
Copyright © 2011-2022 走看看