codeforces-div1-285-D
来源:互联网 发布:邵氏弃儿 后续 知乎 编辑:程序博客网 时间:2024/05/17 08:54
题目链接:Misha and XOR
解法:
首先对于每个数, 先讲其转换为二进制, 转换的方法就是模拟大数除法, 转化的时候最好压缩几位, 这样速度快些.
然后问题其实就变成了, 对于某个二进制数, 能否用出现在它之前的那些二进制数表示.
有点经验的话, 就很容易发现需要用高斯消元法来解决.
但是高斯消元法的复杂度是m^3(m为矩阵大小), 这里一共有n个数, 复杂度就是n*m^3, 对于这里的数据, 明显超时了.
由于这些数是按照顺序加入的, 每加入一个数就询问能否由前面的数组成, 这样就可以根据这个顺序性, 每次加入数过后, 维护一些东西, 以求降低复杂度.
假如现在加入到了第k个数, 那么我们就维护0~k个数构成的矩阵, 转化成阶梯形式过后, 每行现在的值, 每行第一个非0元素的位置, 以及每行被哪些行异或过, 有些拗口, 下面有个例子.
比如第一个元素为 1100(十进制的3), 把这个元素加入过后, 我们维护了第一行的这些东西: 这一行的值为1100, 第一个非0元素在第0位, 构成这一行的数有第1个数;
现在第二个元素为 1000(十进制的2), 先把这个元素加到矩阵的第二行, 于是现在的矩阵为
1100
1000
现在把他变为阶梯矩阵,
1100
0100
现在再来维护第二行的东西: 这一行值为0100, 第一个非0元素在第1位, 构成这一行的数有第1, 2个数(因为这一行实际上是有第一二个数异或得来)
现在考虑一下询问,
假如第三个数是1000(1), 我们就可以根据刚才维护的阶梯矩阵来求解他的值,
首先我们看他第0位是1, 因此我们需要把它和第一行进行异或来抵消这个1, 现在它的值就变成了0100,
然后我们看它第1位是1, 因此我们需要把它和第二行进行异或来抵消这个1, 现在它是0000,
发现它现在是0000, 就说明它能够由之前的数字构成了.
如果异或完后的值不等于0, 那么说明它不能由之前数字构成.
下面是代码
#include <stack>#include <stdio.h>#include <iostream>#include <string.h>#include <vector>#include <math.h>#include <queue>#include <map>#include <set>#include <algorithm>#include <bitset>using namespace std;#define FOR(i, j, k) for(int i=(j);i<=(k);i++)#define REP(i, n) for(int i=0;i<(n);i++)#define mst(x, y) memset(x, y, sizeof(x));#define pii pair<int, int>#define fr first#define sc second#define left myleft#define right myright#define ll long long#define ull unsigned long long#define seed 1331#define eps 1e-5#define pdd pair<double, double>#define inf 1e9const int lim = 2050;int n, first[lim];bitset <lim> row[lim], who[lim], x, ans;char s[666];void read(){scanf("%s", s);}void convert(){ x.reset(); int len = strlen(s), pos = 0; REP(i, len) s[i] -= '0'; while(len){ ll base = (ll)1<<50, remain = 0; int p = 0; REP(i, len){ ll sum = remain*10 + s[i]; if(sum >= base || p) s[p ++] = sum / base; remain = sum % base; } REP(i, 50) x[pos ++] = remain & 1, remain /= 2; len = p; }}int main(){// freopen("4", "r", stdin); cin>>n; REP(k, n){ read(); convert(); ans.reset(); ans.set(k); REP(i, k) if(x.test(first[i])) x ^= row[i], ans ^= who[i]; if(x.any()){ // 如果不为0, 那么输出0, 且把这个数加入矩阵作为一行 puts("0"); REP(i, lim) if(x[i]) {first[k] = i;break;} row[k] = x; who[k] = ans; int p = k; while(p && first[p]<first[p-1]){ swap(first[p], first[p-1]); swap(who[p], who[p-1]); swap(row[p], row[p-1]); p --; } }else{ // 如果为0, 那么直接输出答案 printf("%d", ans.count()-1); REP(i, k) if(ans.test(i)) printf(" %d", i); puts(""); } } return 0;}
- codeforces-div1-285-D
- codeforces-div1-282-D
- codeforces-div1-284-D
- codeforces-div1-286-D
- codeforces 250 div1 D
- Codeforces round339 div1 D
- Codeforces #383 div1 D
- codeforces 319 div1 D(Matrices)
- codeforces 221 div1 D Tree and Queries
- codeforces round# 302 (div1 D 树形计数)
- codeforces round# 296 (div1 D)(bitmasks)
- Codeforces #441 Div1.D:(扩展Lucas)
- Codeforces Round 200 Div1 D Water Tree (树上线段树)
- Codeforces #345 div1 D. Zip-line LIS dp
- Codeforces Round #352 div1 C D (智商+线段树)
- Codeforces Round #445 Div1 D:Symmetric Projections (计算几何)
- codeforces 148 div1
- codeforces 150 div1
- 设计模式心得:适配器模式(adapter pattern)和外观模式(facade pattern)
- jQuery文字和图片列表滚动插件
- 有关于HMAX的资料1
- 测试覆盖率工具
- ext.net 如何传参数
- codeforces-div1-285-D
- Two-stage rotation animation is deprecated. This application should use the smoother single-stage an
- Screen命令使用指南
- 最短路四种算法
- IOS后台运行 之 后台播放音乐
- apk反编译步骤
- MySQL事务
- [Leetcode 179, Medium] Largest number
- 利用OpenCV检测图像中的长方形画布或纸张并提取图像内容