時限:1.5s
空間:64m
給你n ≤5
×107
n\leq5\times10^7
n≤5×10
7個數字,每個數字≤10
9\leq 10^9
≤109
,問你有多少對數字異或起來的值在二進位制下的1
11的個數為奇數個。
這個直接o(n
2)
o(n^2)
o(n2
)列舉計算就可以了,但是是肯定不行的,所以我們要考慮其他方法。
對於兩個數字,某一位異或為1
11的話那麼原來的兩個數字的那一位必須不一樣,如果異或為0
00的話,原來的兩個數字的兩位肯定一樣。
所以我們發現,它某一位從原來的1
11變成0
00的話,必須是同時都為1
11,那麼最後兩個數字的1
11減少的個數和肯定為偶數,所以我們只需要原來的1
11的個數和為奇數,那麼最後消除後剩下的1
11的個數肯定還是奇數,而只有兩個數的1
11的個數分別為一奇一偶,加起來才為奇數個。
110010xor010001
=100011
110010\ \mathbf\ 010001=100011
110010
xor0
1000
1=10
0011
原來有3+2
=5
3+2=5
3+2=5個1
11,而其中的順數第二位,兩個數字都為1
11,所以消去了,剩下3
33個1
11,那麼就為奇數。
11001xo所以最後統計一下奇數個1r00111
=11110
11001\ \mathbf\ 00111=11110
11001x
or00
111=
1111
0原來有3+3
=6
3+3=6
3+3=6個1
11,而順數最後一位都為1
11,消去,剩下4
44個1
11,所以不為奇數。
所以只有原來的1
11的個數為奇數的,最後才能成為答案。
11的個數,那麼答案就是奇數的和偶數的組合,令奇數個1
11的個數為t
tt個,那麼答案就為t×(
n−t)
t\times(n-t)
t×(n−t
)。如果直接統計的話,複雜度為o(n
logv
)o(nlogv)
o(nlog
v)的,而log
vlogv
logv
可以達到30
3030
,那麼複雜度最大為三億,顯然1.5
s1.5s
1.5s
是跑不過的,所以考慮優化:
我們按照位進行分治統計,複雜度降為o(n
logl
ogv)
o(nloglogv)
o(nlog
logv
).我們預處理15
1515
位的所有數的二進位制位的1
11的個數,那麼乙個數字可以看做兩個15
1515
位的數字拼接而成,所以拆開計算和即可,複雜度降為o(2
15+n)
o(2^+n)
o(215+
n)對於統計2
152^
215內的數的二進位制位的個數,我們不用15×2
1515\times 2^
15×215
列舉統計,我們可以用類似dp+
lowb
it
dp+lowbit
dp+low
bit的方式統計(low
bit(
i)=i
&(−i
)lowbit(i)=i\&(-i)
lowbit
(i)=
i&(−
i)為找到二進位制最低位的1
11),轉移如下:
b it
cnt[
i]=b
itcn
t[ix
orlo
wbit
(i)]
+1
bitcnt[i]=bitcnt[i\ \mathbf\ lowbit(i)]+1
bitcnt
[i]=
bitc
nt[i
xorl
owbi
t(i)
]+1我們發現它的實質是每次消除最低位的1
11,所以貢獻+1+1
+1即可。那麼複雜度即為o(2
15)
o(2^)
o(215)
。原題題目位址【in-luogu】
**如下:
#include
#include
#include
#define rg register
#define ll long long
#define lowbit(x) ((x)&(-x))
using
namespace std;
const
int s=
1<<15|
1,s=(1
<<15)
-1;ll n,a,b,c,d,x;
ll t1,bit[s]
;void
init()
}void
calc
(int a)
intmain()
printf
("%lld\n"
,1ll
*(n-t1)
*t1)
;return0;
}
二進位制位運算(與 或 異或 取反)
1.與運算 and 0 and 0 0 全1才1 1 and 0 0 0 and 1 0 1 and 1 1 用途 用來位置0,若想把ffh 11111111b,255d 第 三 五 從右往左 位置0,只需 and 11101011b 235d,e8h 2.或運算 or 0 or 0 0 全0才0 ...
二進位制 二進位制中1的個數
題目 請實現乙個函式,輸入乙個整數,輸出該數二進位制表示中 1 的個數。例如,把 9 表示成二進位制是 1001,有 2 位是 1。因此,如果輸入 9,則該函式輸出 2。示例 1 輸入 00000000000000000000000000001011 輸出 3 解釋 輸入的二進位制串 0000000...
判斷乙個整數二進位制下1的個數
1.最容易想到的就是 n 1 得到最後一位是不是 1 然後再將 n 1 這樣迴圈 int 32次就可以得到1的個數,但是這樣n為負數時會陷入死迴圈 2.不如換乙個思路設定乙個 i 每次讓i 1這樣就不會對n進行修改,避免了死迴圈 public static int getnum3 int n ret...