Number Sequence(hdu 5014)

題目鏈接


題意:給出A數字序列,B序列與之元素相同, 各項對應異或, 求使得異或和最大的B序列。

思路:雖然這道題給出A的序列, 但是要按照從大到小的順序進行異或運算,因爲使得大數異或和達到最大值的數一定比他小, 而這個小數就可以使用最大值和大數異或來找到。

比如: 8 , 二進制是 1000, 異或能夠得到的最大值是 1111, 所以與之匹配的數就爲 1000^1111 = 0111=7。 那麼7的匹配數也就是8了。 從大到小依次計算標記下來, 就得到最大的結果。


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <fstream>
using namespace std;
int Dec[33];
int num[100005];
int vis[100005];
int ans[100005];
void getDec()                  //得到每一位二進制的臨界大小
{
    int i;
    int sum = 1;
    for(i = 0; i < 33; i++)
    {
        Dec[i] = sum;
        sum *= 2;
    }
}
int getMax(int x)            //獲取異或能夠達到的最大值
{
    int i = 0, j = 32, mid;
    while(i <= j)
    {
        mid = (i+j)/2;
        if(x == Dec[mid])
            return Dec[mid+1]-1;
        if(x < Dec[mid])
            j = mid - 1;
        else
            i = mid + 1;
    }
    return Dec[i]-1;
}
int main()
{
    int n;
    int i, j;
    int maxn;
    getDec();
     while(scanf("%d", &n) == 1)
    {

        for(i = 0; i <= n; i++)
           scanf("%d",&num[i]);
        long long int sum = 0;         //int 過不了
        memset(vis, 0, sizeof(vis));
        for(i = n; i >= 0; i--)
        {
            if(!vis[i])
            {
                 vis[i] = 1;
                 maxn = getMax(i);
                 int tmp = maxn^i;
                 if(vis[tmp])
                 {
                     maxn = 0;
                     ans[i] = i;
                 }
                 else
                 {
                    vis[tmp] = 1;
                    ans[i] = tmp;
                    ans[tmp] = i;
                    sum += maxn;
                 }
            }

        }
        cout << sum*2 << endl;
        for(i = 0; i < n; i++)
            cout << ans[num[i]] << ' ';
        cout << ans[num[n]] << endl;
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章