NOIP2017提高A組集訓10 22 幸運值

2021-08-14 21:50:28 字數 1271 閱讀 9207

校慶志願者小z在休息時間和同學們玩卡牌遊戲。一共有n張卡牌,每張卡牌上有乙個數ai,每次可以從中選出k張卡牌。一種選取方案的幸運值為這k張卡牌上數的異或和。小z想知道所有選取方案的幸運值之和除以998244353的餘數。

輸入的第一行有兩個整數n和k。

第二行有n個整數,表示序列a。

乙個整數表示答案。

輸入1:

3 2

1 2 3

輸入2:

10 5

123 456 789 987 654 321 101 202 303 404

輸出1:

6 輸出2:

130776

對於30%的資料滿足,1<=n<=20

對於另30%的資料滿足,1<=n<=100,0<ai<=1024

對於80%的資料滿足,1<=n<=2000

對於100%的資料滿足,1<=n<=100000,0<ai<2^31,1<=k<=n

比賽時我只打了乙個暴力,不知道為什麼還打錯了。

但是這個正解很好理解:

首先我們知道因為題目涉及到的異或運算時關於二進位制的運算,所以我們很容易想到可以把每個數分別拆成二進位制形式。因為位運算只涉及到每一位,所以直接做。

對於每一位,我們統計這些數在這一位上含有一的個數,設其為x,我們得到乙個公式: ∑i

=1kc

(x,i

)∗c(

n−x,

k−i)

∗2j

我們來理解一下這條式子。

首先,i必須是乙個奇數,因為只有有奇數個1時才可以是這一位算出來的值不為零,那麼兩個排列組合就很簡單了,那個2j

表示當前這一位為j,就是這一位的貢獻。

然後我們的排列組合因為要在模意義下,所以要用到逆元。

#include

#include

#define p 998244353

using namespace std;

int n,k;

long long ans;

long long fac[100001];

int a[100001];

long long ksm(long long xx,long long k)

returns;}

intq()

returnx;}

long long c(int n,int

m)int main()

printf("%lld\n",ans);

}

NOIP2017提高A組集訓10 21 總結

今天和學軍 雅禮的dalao們一起切磋,感覺他們太強了。接到題目 t1 一定存在著什麼規律。於是我後來打了個表找了一下規律 顯然 部分大佬們想到t1的部分分的dp 強 t2 一看就知道很可能是dp。我dp很爛,所以先打30分暴力再說。打完之後去想60分。我又根據暴力發現了在遞增序列裡,剩下的後面的數...

NOIP2017提高A組集訓10 30 總結

今天幹了些什麼 看到第一題,我蒙b了 感覺這題之前在 見過,記得好像是將圖斜過來看還是怎樣的。於是去看第二題。第二題乙個很顯然的做法,將邊排序,然後暴力建mst。然而我將時間複雜度多算了乙個0,以為不能過,結果我多加了乙個用來騙分的東西,結果這個騙分的東西打錯了,要騙分的那兩個資料都沒過。55555...

NOIP2017提高A組集訓10 22 幸運值

校慶志願者小z在休息時間和同學們玩卡牌遊戲。一共有n張卡牌,每張卡牌上有乙個數ai,每次可以從中選出k張卡牌。一種選取方案的幸運值為這k張卡牌上數的異或和。小z想知道所有選取方案的幸運值之和除以998244353的餘數。對於30 30 30 的資料滿足,1 n 20 1 le n le20 1 n ...