C.U.P.S.(構造)

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*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章