hdu5014 构造b数列使得t最大(小想法)
生活随笔
收集整理的這篇文章主要介紹了
hdu5014 构造b数列使得t最大(小想法)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ?給你一個序列a,他有n+1個數,每個數的范圍是ai >= 0 && a[i] <= n,同時任意兩個數字都是不相同的,就是ai != aj (i!=j),然后讓你構造一個序列b,這個序列的要求與a序列一樣,最后要求構造的b是使 t = (a0 ^ b0) + (a1 ^ b1) + ...+ (an ^ bn)最大。
思路:
? ? ?給你一個序列a,他有n+1個數,每個數的范圍是ai >= 0 && a[i] <= n,同時任意兩個數字都是不相同的,就是ai != aj (i!=j),然后讓你構造一個序列b,這個序列的要求與a序列一樣,最后要求構造的b是使 t = (a0 ^ b0) + (a1 ^ b1) + ...+ (an ^ bn)最大。
思路:
? ? ? 一開始想的太簡單了,因為題目要求的是每個數字都只能用一次,一開始我的想法是根據n的奇偶,來單獨處理,處理的時候也是根據每個ai的奇偶來處理的,結果wa了,現在來說下正確的解法吧,這個題目我用的正確解法有點貪心的意思,我們每次先找到一個最大的2^k的數字,這個數字要小于等于n,從它開始枚舉,往兩邊擴,如果不能擴了就找到當前沒有被找出來的最大的那個2^k繼續擴,不怎么好解釋,自己在紙上多寫幾個連續的二進制數,然后模擬下很容易懂的,這里面有一個很容易讓人懷疑的地方就是可能大數的那個方向會有剩余,其實不用擔心這個,不可能有剩余,因為如果以某一個數為中心往兩側擴的話,只要前面擴到頭了,也就是到1了,那么后面一定是mark完的了,因為擴到1相當于自己*2了,也就是2^(k+1)了,要是沒有看懂什么意思,那么就自己找幾個連續的二進制數模擬下就行了。
#include<stdio.h> #include<string.h> #include<stack>#define N 110000 using namespace std;int mark[N]; int num[N] ,Ans[N];int main () {int n ,i ,tmp;while(~scanf("%d" ,&n)){for(i = 0 ;i <= n ;i ++)scanf("%d" ,&num[i]);stack<int>my_sk;tmp = 1;while(1){my_sk.push(tmp);tmp <<= 1;if(tmp > n) break;}memset(mark ,0 ,sizeof(mark));memset(Ans ,0 ,sizeof(Ans));while(!my_sk.empty()){int L = my_sk.top() - 1;int R = L + 1;my_sk.pop();while(1){if(L < 0 || R > n || mark[L] || mark[R])break;mark[L] = mark[R] = 1;Ans[L] = R ,Ans[R] = L;L -- ,R ++;}}__int64 ans = 0;for(i = 0 ;i <= n ;i ++)ans += (__int64)(num[i] ^ Ans[num[i]]); printf("%I64d\n" ,ans);for(i = 0 ;i <= n ;i ++)if(i == n) printf("%d\n" ,Ans[num[i]]);else printf("%d " ,Ans[num[i]]);}return 0; }
總結
以上是生活随笔為你收集整理的hdu5014 构造b数列使得t最大(小想法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu2155 小黑的镇魂曲(dp)
- 下一篇: hdu5007 小水题