BZOJ_3668_起床困難綜合癥

About Problem

Solve

題目的意思就是給你一些操作C[1] - C[N],每個操作只有可能是AND(&), OR(|), XOR(^)中的一個。
然后給你一個數(shù)M。
設(shè)f(x)為 x 經(jīng)過操作 C[1] - C[N] 后的得到的答案。
要求:


Score 50%

其實(shí)這個就很簡單的,枚舉每一個M,然后去跑N個步驟,然后找出最優(yōu)解就可以。
復(fù)雜度O(M * N)

Code:

#include <cstdio>
#include <cstring>

#ifdef _WIN32
#define lld I64d
#endif

const int Maxn = int(1e5) + 10;
int n, m, t[Maxn], com[Maxn];

int ans = 0;
void force1()
{
    for(int i = 0; i <= m; ++i)
    {
        int tmp = i;
        for(int j = 1; j <= n; ++j)
            if(com[j] == 1) tmp = tmp & t[j];
            else if(com[j] == 2) tmp = tmp | t[j];
            else if(com[j] == 3) tmp = tmp xor t[j];
        if(tmp > ans) ans = tmp;
    }
    printf("%d\n", ans);
    return;
}

int main()
{
    freopen("sleep.in", "r", stdin);
    freopen("sleep.out", "w", stdout);
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; ++i)
    {
        char s[5];
        scanf("%s %d", s, &t[i]);
        if(s[0] == 'A') com[i] = 1;
        else if(s[0] == 'O') com[i] = 2;
        else if(s[0] == 'X') com[i] = 3;
    }
    if(m <= 1000) force1();
    return 0;
}

Score 100%

既然M高達(dá)1e9,那么很明顯不能枚舉M了。
那我們換個思路,既然這里都是二進(jìn)制計算,那么這些二進(jìn)制計算有一個非常顯著的特點(diǎn),就是它的每一位都是相對獨(dú)立的。
舉個例子來說:

6 = 1 1 0
5 = 1 0 1
6 ^ 5 = 0 1 1
當(dāng)你在計算從左往右數(shù)第2位時, 第一位和第三位均不會影響第二位的運(yùn)算結(jié)果。

我們假設(shè)最后的答案是從 K 經(jīng)過N步后得到的 f(K)。
那么我們是不是可以枚舉 K 的每一個二進(jìn)制位,然后看 K 的第 i 個二進(jìn)制位為1更優(yōu) 還是為0更優(yōu)。
最后得到每一個二進(jìn)制位的最有值,在貪心選取,看看得到的K會不會超過M。
再求出f(K)就OK了。
由于答案在1e9內(nèi),所以不會超過32位。
每位可以進(jìn)行N次操作,所以復(fù)雜度為O(32 * N)

Code:

#include <cstdio>
#include <cstring>

const int Maxn = (int)1e5 + 10;
int num[Maxn][40], t[Maxn], ans[40];
int N = 0;

int main()
{
    freopen("sleep.in", "r", stdin);
    freopen("sleep.out", "w", stdout);
    
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; ++i)
    {
        char s[5];
        scanf("%s %d", s, &t[i]);
        if(s[0] == 'A') num[i][0] = 1;
        else if(s[0] == 'O') num[i][0] = 2;
        else if(s[0] == 'X') num[i][0] = 3;
        int tmp = t[i], l = 0;
        while(tmp)
        {
            num[i][++l] = tmp % 2;
            tmp /= 2;
        }
    }
    for(int i = 31; i; --i)
    {
        int z = 0, o = 1;
        for(int j = 1; j <= n; ++j)
        {
            if(num[j][0] == 1) z &= num[j][i], o &= num[j][i];
            else if(num[j][0] == 2) z |= num[j][i], o |= num[j][i];
            else if(num[j][0] == 3) z = z xor num[j][i], o = o xor num[j][i];
        }
        if(o > z) ans[i] = 1;
        else ans[i] = 0;
    }
    for(int i = 31; i; --i)
        if(N + (ans[i] << (i-1)) <= m) N += (ans[i] << (i - 1));
    for(int i = 1; i <= n; ++i)
    {
        if(num[i][0] == 1) N &= t[i];
        else if(num[i][0] == 2) N |= t[i];
        else if(num[i][0] == 3) N ^= t[i];
    }
    printf("%d\n", N);
    return 0;
}


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 一年級語文上冊生字表 生字表一(共400字) 啊(ā)愛(ài)安(ān)岸(àn)爸(bà)八(bā)巴(bā)...
    meychang閱讀 2,846評論 0 6
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,739評論 18 399
  • 不知道想要什么 不知道什么是對 什么是錯 怎樣才能快樂。想自殺都沒用勇氣 活卻也沒有太大意義。變不好 壞卻沒有止境...
    澄澴閱讀 161評論 0 0
  • 歡迎戳進(jìn)來【歸塵】目錄 【上一章】歸塵(21)波月洞 仙陣之中的那頭遮天蔽日的巨獸此時全身血紅,他在燃燒自己的獸丹...
    傅人閱讀 503評論 23 14
  • 在這個流行拍美照曬票圈、微博獲取好友點(diǎn)贊的時代里,會拍照簡直是不可缺少的技能。經(jīng)常會看到廚藝界的網(wǎng)紅博主曬他們的廚...
    有櫝閱讀 292評論 0 0