题解 | #F1. Korney Korneevich and XOR (easy version)#

F1. Korney Korneevich and XOR (easy version)

题意

给定长度为n的序列a[n],对于a[n]中的任意上升子序列(不连续),其XOR值都加入答案的集合中,求这个答案集合。

首先,任意两个a,b512a, b \le 512ab512a \bigoplus b \le 512 ,这样最后答案的集合大小不会超过512,这提示我们可能是一个f(1e5,512)f(1e5, 512) 的DP. 设状态方程为 f(i,j) f(i, j)表示前ii个元素中,异或值为jj的序列的末位元素最小值。于是得到状态转移方程:

f(i,ja[i])=f(i1,ja[i])f(i,j \bigoplus a[i])=f(i-1,j \bigoplus a[i])

a[i]ja[i] \ge j,有f(i,ja[i])=min(f(i1,ja[i]),a[i])f(i,j \bigoplus a[i])=min(f(i-1,j \bigoplus a[i]), a[i])

这个方程可以优化成一维,且不影响正确性

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int a[N];
int f[N];
int main() {
    int n; cin >> n;
    for(int i = 1; i <= n; i ++) {
        cin >> a[i];
    }
    memset(f, 0x3f, sizeof f); f[0] = 0;
    for(int i = 1; i <= n; i ++) {
        for(int j = 0; j < 512; j ++) {
            if(f[j] < a[i]) {
                f[j ^ a[i]] = min(f[j ^ a[i]], a[i]);
            }
        }
    }
    vector<int> ans;
    for(int i = 0; i < 512; i ++) {
        if(f[i] != 0x3f3f3f3f) ans.push_back(i);
    }
    cout << ans.size() << endl;
    for(auto &it: ans) cout << it << ' ';
}

全部评论

相关推荐

02-22 18:38
门头沟学院 Java
程序员牛肉:标准的NPC简历,一个短链接+12306。你可以在牛客上面搜一搜有多少人的简历和你一样。你自己能不能给出你一个理由让面试官在大家简历高度相同的情况下,选择约面你而不是对应的211,985学生? 是因为你即将拥有的那段小厂实习吗?这种小厂实习真的很有含金量吗?因此你可以找实习,但是你如果只能找到小厂实习的话,其实意义不太大。 但你的时间是充足的,相信我:从现在到今年的九月份大三上你就干两个事情:"写博客"+“参加开源之夏”。这两个搞好了不亚于一段大厂实习的含金量。 想要让自己变得更强,首先就是不要把自己当打工人看待,让自己简历上面的活人气息更多一点,不要让自己成为流水线的产物。你不是在出售你的技能,你是在利用你的技能和公司达成一种合作关系。
点赞 评论 收藏
分享
CVTE校招内推:可以试试我们这,硬件还没招满
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务