bzoj:1299: [LLH邀请赛]巧克力棒
原题:http://www.lydsy.com/JudgeOnline/problem.php?id=1299
众多dalao的题解已经很详细了:http://blog.csdn.net/wzq_qwq/article/details/47258871
这里我只补充一下用高斯消元的方法优化到14*14*30的时间复杂度,而不是2^14
目标是求出是否有一种取数方案使异或和为0
那么按位拆分一下,得到30个方程,但是只有14个变量。解是肯定存在的(全部不取),但是我们希望解的数量大于一。由于解的数量为2^(自由元数量),那么只要有自由元就是有解,也就是不满秩即有解。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<algorithm> #define MN 1000 using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } const int N=30; int n,m,T,a,b[MN][30]; bool Guass(){ int i,j,k; for (i=0;i<n;i++){ for (j=i;j<N;j++) if (b[j][i]){ for (k=i;k<n;k++) swap(b[j][k],b[i][k]); break; } if (j==N) return 1;//不满秩 for (j=i+1;j<N;j++) if (b[j][i]) for (k=i;k<n;k++) b[j][k]^=b[i][k]; } return 0; } int main(){ int i,j; T=10; while(T--){ n=read(); for (i=0;i<n;i++) for (a=read(),j=0;j<N;j++) b[j][i]=(a>>j)&1; puts(Guass()?"NO":"YES"); } }