【高斯消元】[SGU275]To xor or not to xor
2016-01-31 09:15
393 查看
题目大意
从N个数中选出任意个数,使XOR和最大分析
我们贪心地思考这道题,每次,我们从最高位开始枚举答案的每一位,并且总是尝试使这一位为1,并和前面所有的方程联立求解,由于数据最大为101810^{18},1018<26010^{18}<2^{60},所以最多枚举60位,每次用高斯消元的复杂度为为O(n∗602)O(n*60^2),然后枚举60位,复杂度为O(n∗603)O(n*60^3)解法
算法1:在线高斯消元法
当然,有一种求异或方程的在线算法,新增加的方程,和前面的方程联立求解的时候只需要O(n∗60)O(n*60)的时间复杂度,,然后枚举60位,复杂度为O(n∗602)O(n*60^2)如果再加上压位优化,复杂度为O(n∗60232)O(\frac{n*60^2}{32})
[code]#include<cstdio> #include<algorithm> using namespace std; typedef long long LL; typedef unsigned int uint; #define MAXN 100 #define D 32 const int equ=63; int n,var,row; LL b[MAXN+10],ans,c[MAXN+10]; unsigned int a[equ+10][4]; template<class T> void Read(T &x){ char c; while(c=getchar(),c!=EOF) if(c>='0'&&c<='9'){ x=c-'0'; while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0'; ungetc(c,stdin); return; } } void read(){ Read(n); int i,j; for(i=0;i<n;i++) Read(b[i]); var=n; for(i=1;i<=equ;i++) for(j=0;j<var;j++) a[i][j/D]|=((b[j]>>(equ-i))&1)<<(j%D); } void gaussian_elimination(){ int i,j,qv1=var/D,qv2=var%D; for(row=1;row<=equ;row++){ a[row][qv1]|=1<<qv2; for(i=0;i<var;i++) if(a[row][i/D]&(1<<(i%D))){ if(!c[i]){ c[i]=row; break; } else if(c[i]) for(j=0;j<4;j++) a[row][j]^=a[c[i]][j]; } ans<<=1; if(i==var&&(a[row][qv1]&(1<<qv2))) a[row][qv1]=0; else ans|=1; } } int main() { read(); gaussian_elimination(); printf("%I64d",ans); }
算法2:利用高斯约当消元法的性质
我们把刚刚的算法一的矩阵(不包括常数项)逆时针旋转90°,即每一行为一个数字,每一列为每一位。我们发现,只要我们做高斯约当消元,就可以很容易的保证当前列的异或和为一。所以,我们做完高斯消元后,将得到的矩阵一行一行的异或起来,就能得到答案。
[code]#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 100 typedef long long LL; int n,equ,var=64,row; LL a[MAXN+10],ans; template<class T> void Read(T &x){ char c; while(c=getchar(),c!=EOF) if(c>='0'&&c<='9'){ x=c-'0'; while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0'; ungetc(c,stdin); return; } } void read(){ Read(n); equ=n; for(int i=1;i<=n;i++) Read(a[i]); } void gauss_jordan(){ int i,col; for(row=col=1;row<=equ&&col<=var;row++,col++){ if(!(a[row]>>(var-col))&1) for(i=row;i<=n;i++) if(a[i]>>(var-col)&1){ swap(a[i],a[row]); break; } if(!(a[row]>>(var-col))&1){ row--; continue; } for(i=1;i<=equ;i++) if(i!=row&&(a[i]>>(var-col))&1) a[i]^=a[row]; } row--; } void print(){ for(int i=1;i<=row;i++) ans^=a[i]; printf("%I64d",ans); } int main() { read(); gauss_jordan(); print(); }
相关文章推荐
- addslashes()、stripslashes()和magic_quotes_gpc
- Excel自己定义纸张打印设置碰到无法对上尺寸的问题
- KM算法
- 自定义旋转的ProgressBar
- Cocos2d-x 3.1.1 Lua实例-AccelerometerTest(重力加速计)
- 苹果 企业 开发者账号 注册、申请续费整个流程($299的账号)
- android项目中刷新activity界面
- UESTC-888-Absurdistan Roads(kruskal+floyd)
- [LeetCode] Binary Tree Upside Down 二叉树的上下颠倒
- Java设计模式编程中的工厂方法模式和抽象工厂模式
- 数学符号及读法大全
- HDOJ 5616-Jam's balance【模拟】
- Eclipse下通过Maven的Jetty插件运行Web工程的配置
- 把字符串转换为整数
- 通过条件的查询----涉及到三层(Action Service DAO)
- 2015杂谈
- poj 1704 Georgia and Bob(阶梯博弈)
- 奔小康赚大钱 hdu 2255
- ios-提升之【1】-UIApplication
- 2016太原网络营销师郭文军分享网站中如何合理布局关键词?