EOJ 3300 奇數統計(高維字首和)

2022-07-17 11:24:09 字數 1538 閱讀 5052

題目大意:

給n個數,求在n個數中選兩個數(可重複),使得這兩個數的組合數是奇數,求總共有多少種取法。

解題思路:

組合數cn

m奇偶性判斷:

n & m == m 成立則組合數為奇數

一開始沒什麼的思路,直接暴力超時,後來看到lucas定理,發現上面那個式子的本質就是從這裡推導出來的。

lucas定理:

組合數判斷奇數的話就是轉化成上述定理中p = 2

是否為1,利用lucas定理,先把

和化為二進位制,這樣它們都是01序列了。我們又知道

。這樣中為0的地方對應的

中的位置只有一種可能,那就是0

這樣n&m = m的本質就是二進位制中n對應的0得地方,m也對應為0。

然而,就是這個本質,就可以解這道題目

有位大佬一句話點醒了我,n&m = m說明m是n的子集。

對的,用二進位制表示子集的時候,就是這樣,m是n的子集,等價於n為0的位置m一定為0,n為1

的位置,m可以為1,可以為0。

然後對於每個n,求出它的子集的數目即可。

對於求子集,大佬教的方法是高維字首和,**很簡單,就三行,和狀態壓縮dp一樣。

1

for(int i = 0; i < m; i++)

28 }

舉個例子,sum[0101] = sum[0101] + sum[0100] + sum[0001] + sum[0000]

sum[i]就表示i二進位制的所有子集的權值之和

對於組合數n & m == m  m是n的子集,

先統計每個數出現的次數,然後對於每個數,統計它的子集的個數即可,最後答案相加。

1 #include2

using

namespace

std;

3const

int maxn = 1e6 + 10

;4 typedef long

long

ll;5

ll a[maxn], sum[maxn];

6int

main()720

int m = 17;21

for(int i = 0; i < m; i++)

2228

}29 ll ans = 0;30

for(int i = 0; i < n; i++)

31 ans +=sum[a[i]];

32 cout

34return0;

35 }

SSL ZYC 奇數統計

題目大意 給出n個正整數,其中只有乙個數出現了奇數次,其餘的數都出現偶數次。求那個出現了奇數次的數。思路 直接暴力!下面給出兩種做法 1 不保險的 桶排 2 保險的 快排 這道題個人認為快拍更加保險。因為題目沒有告訴你這個數字最大是多少,使用桶排有可能會爆記憶體。雖然這道題用快排比桶排慢,但是更加保...

1547 奇數統計(count)

題目描述 給出n個正整數,其中只有乙個數出現了奇數次,其餘的數都出現偶數次。求那個出現了奇數次的數。1 n 500000,n肯定是奇數。所有出現數都不超過10000。輸入 第一行是n,下一行有n個正整數。輸出 出現了奇數次的數。樣例輸入 樣例輸入1 931 22171 3173 樣例輸入2 5 12...

EOJ2846 統計字串個數

在 0 和 1 組成的長度為 的字串中,輸出不包含 101 子串的字串的個數。本題有多組測試資料。每組測試資料佔一行,含乙個正整數 表示字串的長度。n 1 表示輸入結束。對每組測試資料,在一行中輸出表示不包含 101 子串的字串的個數。如果結尾為0,那麼不包含101的有d n 1 個 如果結尾為1,...