輸出一行,乙個整數表示答案。示例1
複製
2複製1 2
對於此題來說,拋去所有附加條件不管,是乙個mst問題。然鵝對於這種資料範圍,即使處理了重複的點再去建邊跑kruskal也是不科學的(將信將疑於是乎我們來思考別的解法。首先,毋庸置疑,肯定是去重,因為異或相同為0嘛,沒有花費當然要連咯。
其次,對於最小花費,只要全為奇數或偶數肯定是0嘛。
說到這裡肯定有很多小夥伴噴我,然鵝原題面就是這樣的,後來經過和出題人一頓bbox,他才把題面改了。。。
從此時起,一切就變了。lowbit的定義變成了最低非0位(一開始寫的是最低位),所以我們開始找最低的那個1在哪。
關於這個最低的非0位,需要滿足乙個條件,就是在這一位上,其他所有點的權值轉化為二進位制後的這一位,得異或出來乙個1。
怎樣才能異或出來乙個1呢,相信大家大一的時候上大計基課都學過異或的口訣,「相同為0,不同為1」,所以只要所有的點權值轉化為二進位制後,這一位有0又有1就好啦。
如何找到這一位呢,我們從最基礎的角度思考(因為我只會點基礎),利用&1的操作就可以辣,所以我們只要當找不到乙個位上有0又有1時(gay圈現狀),就把權值右移1位,直到找到某一位上有0又有1為止。
如果還有不太清楚的同學可以試試去掉注釋,輸出過程看看,手動寫寫就知道了。
1 #include 2view code#define dbg(x) cout << #x << "=" << x << endl34
using
namespace
std;
5 typedef long
long
ll;6
const
int kmaxn = 3e5 + 7;7
8int
a[kmaxn];
9set
s[37
];10
int f[35][2
];11
12 templateinline void read(t &res)
1318
19namespace
_buff
27return ib == ie ? -1 : *ib++;28}
29}3031
intqread()
39if (c == '-'
) 43
for (; c >= '
0' && c <= '
9'; c =getc())
46return pos ? ret : -ret;47}
4849
intmain()
5059
/*60
printf("f[0][0]:%d f[0][1]:%d\n",f[0][0],f[0][1]);
61int d = s[0].size();
62for(set::const_iterator p = s[0].cbegin(); p != s[0].cend(); ++p)
65*/
66 ll ans = 0;67
for(int i = 0; i <= 30; ++i)
72for
(auto it : s[i])
76/*
77printf("f[%d][0]:%d f[%d][1]:%d\n",i,f[i][0],i,f[i][1]);
78int d1 = s[i].size();
79for(set::const_iterator p = s[i].cbegin(); p != s[i].cend(); ++p)
82*/83}
84 cout << ans <
85return0;
86 }
牛客寒假演算法基礎演算法訓練營2
1 座與重修費 題目描述 期末考試結束了,座發現很多人掛了大物,只能等著第二年重修,還要交400元的重修費。座突然想起有個學長和他講過,如果學校哪一年缺錢了,那一年的大物試卷就會特別難。現在 座有了所有人的成績,座想知道如果所有掛科的人都在第二年重修,學校能賺多少重修費?掛科是指一門課的分數小於60...
牛客寒假演算法訓練營第二場 I建通道
首先,我們要建立的是乙個最小生成樹 跟最小生成樹其實沒關係 這些資料在位運算時有一些規律 1.兩個相同的數lowbit 結果為0,所以如果有兩個點的權值相同我們一定會讓他們兩個相連,由此,我們可以先對權值進行排序去重,去重後的權值個數是我們後面要計算的權值,那些相同的權值,因為我們要把它們連起來,並...
牛客寒假演算法基礎訓練營6
早知道這次題目這麼簡單就認真做了,最後一場沒心做,後面懶得想了,唉罪過罪過 1 煤氣灶 題目描述 小j開始打工,準備賺錢買煤氣灶。第一天,小j的工資為n元,之後每天他的工資都比前一天多d元。已知煤氣灶需要m元,求小j最少工作幾天才能買到煤氣灶。輸入描述 四個整數 n,m,d,x 分別表示小j第一天的...