01串出現奇數個1的方案數 2016四川省賽 Odd Discount

題目鏈接:https://acm.bnu.edu.cn/v3/problem_show.php?pid=52300

先證明結論,後說題目;
結論1:長度爲n的01序列出現奇數個1的方案爲總方案的1/2(即出現奇數個1和出現偶數個1的方案數相等)
證明:(數學歸納法)
n=1的情況,顯然成立;
如果n=i成立:那麼再額外增加1個1,奇數個1和偶數個1的方案會對調;再額外增加1個0,奇數個1和偶數個1的方案不變;因此n=i+1也成立;
所以長度爲n的01序列出現奇數個1和出現偶數個1的方案數相等

結論2:長度爲n的01序列,限制某長度爲m的子序列出現奇數(或偶數)個1。滿足條件的方案數爲總方案的1/2(即2n1
證明:由結論1知,子序列的合法方案爲2m1 ,剩餘部分可隨便取,合法方案爲2nm ,故總的方案爲2n1

結論3:長度爲n的01序列,限制兩個不同的子序列出現奇數(或偶數)個1。滿足條件的方案數爲總方案的1/4(即2n2
證明:
情況1.兩個子序列不相交時,由結論2易知,爲原來的1212=14
情況2.一個子序列被另一個包涵時,要滿足相交部分是奇數個,不相交部分是偶數個,轉化爲了情況1,所以1/4;
情況3.兩個子序列相交時(不包涵),分兩種情況討論:
(1).相交部分有奇數個1(由結論2可知這種方案是總方案的1/2),剩餘部分轉化爲情況1,所以1/8;
(2).相交部分偶數個1,同上;
所以是18+18=14

事實證明,長度爲n的01序列,確定m個不同子序列的1個數的奇偶性,則符合條件的方案數爲2nm

題意:有n件物品可以購買,有m種折扣。折扣i有ki個要求物品,如果ki個要求的物品中購買了奇數個,就可以得到這個折扣的值ci。顯然有2^n-1種購買方案。對於一種購買方案,它的價值是獲得折扣的和的平方。要求輸出,所有方案的價值和。

分析:
先把所有條件一樣的折扣累加在一起。
n個物品買或不買構成了01序列。
對於一種購買方案i,其對答案的貢獻是:
(ci1+ci2+ci3....+cik)2=kj=1c2ij+2p,q(p!=q)cipciq

分別計算每一項在多少種購買方案中出現。
平方項在滿足對應條件時出現,出現2n1
兩個c相乘,在同時滿足兩個條件時出現,出現2n2

#include<bits/stdc++.h>
const int Z = 1e9+7;
int v[1<<20];
int main()
{
    int n,m,c,k,sta,a,ret=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        sta=0;
        scanf("%d%d",&c,&k);
        while(k--) scanf("%d",&a),sta|=1<<a-1;
        v[sta]=(v[sta]+c)%Z;
    }
    if(n==1)res=1ll*v[1]*v[1]%Z;
    else
    {
        int tmp=0;
        for(int i=1;i<(1<<n);i++)
            tmp=(tmp+v[i])%Z,
            res=(res+1ll*v[i]*v[i]%Z)%Z;
        res=(res+1LL*tmp*tmp)%Z;
        for(int i=1;i<=n-2;i++) res=2ll*res%Z;
    }
    printf("%d\n",res);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章