Codeforces839 D. Winter is here(容斥+式子化简)

题意:

在这里插入图片描述
数据范围:n<=2e5,a(i)<=1e6

解法:

显 然 只 需 要 计 算 出 每 种 g c d 的 所 有 子 序 列 的 长 度 和 . 令 d [ i ] 表 示 g c d 为 i 的 长 度 和 , 那 么 a n s = ∑ i ∗ d [ i ] 考 虑 通 过 容 斥 计 算 d [ i ] : d [ i ] = g c d 为 i 的 倍 数 的 长 度 和 − d [ i ∗ 2 ] − d [ i ∗ 3 ] . . . . . . 剩 下 的 问 题 为 g c d 为 i 的 倍 数 的 长 度 和 如 何 计 算 : 设 有 c n t 个 i 的 倍 数 , 那 么 长 度 和 为 : C ( c n t , 1 ) ∗ 1 + C ( c n t , 2 ) ∗ 2 + . . . + C ( c n t , c n t ) ∗ c n t , 即 ∑ i = 1 c n t C ( c n t , i ) ∗ i . 试 着 化 简 一 下 : ∑ i = 1 c n t C ( c n t , i ) ∗ i = ∑ i = 1 c n t c n t ! i ! ∗ ( c n t − i ) ! ∗ i = ∑ i = 1 c n t c n t ! ( i − 1 ) ! ∗ ( c n t − i ) ! = ∑ i = 1 c n t ( c n t − 1 ) ! ( i − 1 ) ! ∗ ( c n t − i ) ! ∗ c n t = ∑ i = 1 c n t C ( c n t − 1 , i − 1 ) ∗ c n t = c n t ∗ ∑ i = 1 c n t C ( c n t − 1 , i − 1 ) = c n t ∗ ∑ i = 0 c n t − 1 C ( c n t − 1 , i ) = c n t ∗ 2 c n t − 1 显然只需要计算出每种gcd的所有子序列的长度和.\\ 令d[i]表示gcd为i的长度和,那么ans=\sum i*d[i]\\ 考虑通过容斥计算d[i]:\\ d[i]=gcd为i的倍数的长度和-d[i*2]-d[i*3]......\\ 剩下的问题为gcd为i的倍数的长度和如何计算:\\ 设有cnt个i的倍数,那么长度和为:\\ C(cnt,1)*1+C(cnt,2)*2+...+C(cnt,cnt)*cnt,\\ 即\sum_{i=1}^{cnt}C(cnt,i)*i.\\ 试着化简一下:\\ \sum_{i=1}^{cnt}C(cnt,i)*i\\ =\sum_{i=1}^{cnt} \frac{cnt!}{i!*(cnt-i)!}*i\\ =\sum_{i=1}^{cnt} \frac{cnt!}{(i-1)!*(cnt-i)!}\\ =\sum_{i=1}^{cnt} \frac{(cnt-1)!}{(i-1)!*(cnt-i)!}*cnt\\ =\sum_{i=1}^{cnt}C(cnt-1,i-1)*cnt\\ =cnt*\sum_{i=1}^{cnt}C(cnt-1,i-1)\\ =cnt*\sum_{i=0}^{cnt-1}C(cnt-1,i)\\ =cnt*2^{cnt-1} gcd.d[i]gcdi,ans=id[i]d[i]:d[i]=gcdid[i2]d[i3]......gcdi:cnti,:C(cnt,1)1+C(cnt,2)2+...+C(cnt,cnt)cnt,i=1cntC(cnt,i)i.:i=1cntC(cnt,i)i=i=1cnti!(cnti)!cnt!i=i=1cnt(i1)!(cnti)!cnt!=i=1cnt(i1)!(cnti)!(cnt1)!cnt=i=1cntC(cnt1,i1)cnt=cnti=1cntC(cnt1,i1)=cnti=0cnt1C(cnt1,i)=cnt2cnt1

code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxm=1e6+5;
const int mod=1e9+7;
int cnt[maxm];
int p2[maxm];
int d[maxm];
int a[maxm];
int n;
void solve(){
    p2[0]=1;
    for(int i=1;i<maxm;i++)p2[i]=p2[i-1]*2%mod;
    cin>>n;
    for(int i=1;i<=n;i++){
        int x;cin>>x;
        a[x]++;
    }
    for(int i=1;i<maxm;i++){//cnt[i]=i的倍数.
        for(int j=i;j<maxm;j+=i){
            cnt[i]+=a[j];
        }
    }
    for(int i=maxm-1;i>=2;i--){
        if(!cnt[i])continue;
        d[i]=cnt[i]*p2[cnt[i]-1]%mod;
        for(int j=i+i;j<maxm;j+=i){
            d[i]=(d[i]-d[j])%mod;
        }
    }
    int ans=0;
    for(int i=2;i<maxm;i++){
        ans=(ans+i*d[i]%mod)%mod;
    }
    ans=(ans%mod+mod)%mod;
    cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(0);
    solve();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值