zoukankan      html  css  js  c++  java
  • [cf839d]Winter is here容斥原理

    题意:给定一个数列${a_i}$,若子序列长度为$k$,最大公约数为$gcd$,定义子序列的权值为$k*gcd (gcd  > 1)$。求所有子序列的权值和。 答案对10^9+7取模。

    解题关键:容斥原理求序列中各$gcd$的个数,亦可用莫比乌斯函数。

    逆序求的话,前面直接减后面的个数,在后面一项就相当于相加了,如此往复。

    关于知道所有$gcd$为$n$的个数之后答案的求法:

    法一:

    $egin{array}{l}
    1C_n^1 + 2C_n^2 + ... + nC_n^n\
    = n(C_{n - 1}^1 + C_{n - 1}^2 + ... + C_{n - 1}^{n - 1})\
    = n{2^{n - 1}}
    end{array}$

    法二:

    $egin{array}{l}
    [{(x + 1)^n}]' = n{(x + 1)^{n - 1}}\
    {(x + 1)^n} = sumlimits_{i = 1}^n {C_n^i{x^i}} \
    n{(x + 1)^{n - 1}} = sumlimits_{i = 1}^n {C_n^ii{x^{i - 1}}}
    end{array}$

    法三:逆序相加

    容斥解法:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int mod=1e9+7;
     5 #define inf 0x3f3f3f3f
     6 ll c[1000004],pw[1000007],sum[1000007];
     7 int main(){
     8     ll n,x,mx=-inf;
     9     cin>>n;
    10     pw[0]=1;
    11     for(int i=1;i<=n+3;i++) pw[i]=pw[i-1]*2%mod;
    12     for(int i=0;i<n;i++) cin>>x,c[x]++,mx=max(mx,x);//hash一下 
    13     ll ct;
    14     ll ans=0;
    15     for(int i=mx;i>1;i--){
    16         ct=0;
    17         for(int j=i;j<=mx;j+=i){
    18             ct=(ct+c[j])%mod;
    19             sum[i]-=sum[j];
    20         }
    21         sum[i]=(sum[i]+ct*pw[ct-1]%mod+mod)%mod; 
    22         ans=(ans+sum[i]*i%mod+mod)%mod;
    23     }
    24     cout<<ans<<"
    ";
    25     return 0;
    26 }

     莫比乌斯反演解法:

     1 #include<bits/stdc++.h>
     2 #define inf 0x3f3f3f3f
     3 using namespace std;
     4 typedef long long ll;
     5 const int mod=1e9+7;
     6 ll mu[1000020],c[1000060],cnt[1000050],pw[1000050],g[1000050];
     7 void sievemu(int n){
     8     mu[1]=1;
     9     for(int i=1;i<=n;i++){
    10         for(int j=i+i;j<=n;j+=i){
    11             mu[j]-=mu[i];
    12         }
    13     }
    14 }
    15 
    16 int main(){
    17     sievemu(1000005);
    18     ll n,x,mx=-inf;
    19     cin>>n;
    20     pw[0]=1;
    21     for(int i=1;i<=n;i++) pw[i]=pw[i-1]*2%mod;
    22     for(int i=0;i<n;i++) cin>>x,c[x]++,mx=max(mx,x);
    23     for(int i=2;i<=mx;i++){
    24         ll ss=0;
    25         for(int j=i;j<=mx;j+=i){
    26             ss+=c[j];
    27         }
    28         if(ss) cnt[i]=ss*pw[ss-1]%mod;
    29     }
    30     //计算gcd倍数的个数
    31      
    32     //对答案进行莫比乌斯反演 
    33     ll ans=0;
    34     for(int i=2;i<=mx;i++){
    35         for(int j=i;j<=mx;j+=i){
    36             g[i]=(g[i]+cnt[j]*mu[j/i]%mod+mod)%mod;
    37         }
    38         ans=(ans+i*g[i]%mod+mod)%mod;
    39     }
    40     cout<<ans<<"
    ";
    41     return 0;
    42 }
  • 相关阅读:
    java读取properties文件的几种方法
    mysql中的一些操作
    Threalocal的使用及其原理
    ResourceBundle和properties 读取配置文件区别
    (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
    mysql中的unique
    JSP标签 <meta> 的作用
    面向对象、匿名内部类
    Katalon Studio 安装 配置 简单使用
    Sonar 规则
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7398397.html
Copyright © 2011-2022 走看看