https://vjudge.net/problem/Gym-102536B
题意:
给出一个n长01串,找出不超过n个01串,满足1的个数恰好为m,所有01串异或起来全部为1。
解析:
可以考虑将所有串分为两种:
- 单个串使用,可以改变位数m。
- 两个串一起用,可以改变位数为2m,2m-2,2m-4…。
由于不要求最少,所以可以两个串改两个位置例如1111 10,1111 01。
如果开始时剩余0的数量为奇数,此时如果m偶数则不行,否则改变m位,使剩下的0的数量为偶数。之后两个两个消除0。
正确性:
第一次奇数变偶数一定可以剩下一个1,之后2换2,所以一定可以在n个之内消除完0。
注意特判一些情况。
代码:
/*
* Author : Jk_Chen
* Date : 2020-03-15-13.19.24
*/
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n'
const LL mod=1e9+7;
const int maxn=100;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/
char x[maxn];
char ans[maxn][maxn];
int main(){
int t=rd;
while(t--){
int n=rd,m=rd;
rep(i,1,n){
rep(j,1,n)ans[i][j]='0';
ans[i][n+1]='\0';
}
scanf("%s",x+1);
vector<int>Z,O;
rep(i,1,n){
if(x[i]-'0')O.pb(i);
else Z.pb(i);
}
if(Z.empty()){
puts("0");
continue;
}
if(Z.size()%2&&!(m%2)){
puts("CATACLYSM IMMINENT - TIME TO HOARD FACE MASKS");
continue;
}
if(Z.size()&&m==n){
if(Z.size()==n){
printf("1\n");
rep(i,1,n)putchar('1');
puts("");
continue;
}
puts("CATACLYSM IMMINENT - TIME TO HOARD FACE MASKS");
continue;
}
int now=0;
if(Z.size()%2){
if(Z.size()>=m){
now++;
rep(i,1,m){
ans[now][Z.back()]='1';
O.pb(Z.back());
Z.pop_back();
}
}
else{
now++;
vector<int>tZ,tO;
int nZ=Z.size();
int nO=m-nZ;
rep(i,1,nZ){
tZ.pb(Z.back());
ans[now][Z.back()]='1';
Z.pop_back();
}
rep(i,1,nO){
tO.pb(O.back());
ans[now][O.back()]='1';
O.pop_back();
}
while(tZ.size()){
O.pb(tZ.back());tZ.pop_back();
}
while(tO.size()){
Z.pb(tO.back());tO.pop_back();
}
}
}
while(Z.size()){
now+=2;
int a1=Z.back();Z.pop_back();
int a2=Z.back();Z.pop_back();
int ct=m-1,ar=1;
while(ct){
if(ar!=a1&&ar!=a2){
ans[now-1][ar]='1';
ans[now][ar]='1';
ct--;
}
ar++;
}
ans[now-1][a1]='1';
ans[now][a2]='1';
}
assert(now<=n);
rep(i,1,n){
int sta=x[i]-'0';
rep(j,1,now){
sta^=ans[j][i]-'0';
}
if(!sta)while(1);
}
printf("%d\n",now);
rep(i,1,now){
puts(ans[i]+1);
}
}
return 0;
}
/*
100
4 4
0000
4 2
1100
5 3
11110
7 7
1111111
7 7
1111110
7 1
1111110
10 9
1001101101
*/
/*_________________________________________________________end*/