• [Contest on 2022.5.27] 我还是一道题都不会做


    \(\cal T_1\) 矩阵

    Description

    有一个 \(n\times n\) 的矩阵,初始时所有位置上都是零。每次操作你可以选择若干行和若干列,然后把这些行列交点处的位置都变成 \(1\).

    现在,你需要在不超过 \(Q\) 次操作内,使得 \((i,j)\) 是零当且仅当 \(j\leqslant i\leqslant j+1\).

    例如 \(n=5\) 时,你需要得到如下的矩阵:

    01111
    00111
    10011
    11001
    11100
    

    \(n\leqslant 3000,Q=26\).

    Solution

    构造一生之敌

    首先可以简化这个问题,先考虑只有对角线为零的情况:发现对角线可以表示为 \(x=y\),于是枚举行列二进制数的每一位 \(k\),将 "行的第 \(k\) 位为零,列的第 \(k\) 位为 \(1\)","行的第 \(k\) 位为 \(1\),列的第 \(k\) 位为零" 的下标全置为 \(1\),那么最后只有对角线不会被置为 \(1\).

    但是现在我们还要维护对角线下面一格。不妨将图形 "缩放" 一下,大概地 将上下两格缩成一格,不就又成一条对角线了嘛?观察得知,奇偶性相同的列的格子缩起来比较符合对角线,因为这样分类能恰好将两个零缩成一个格子,以奇数列为例,就是一二行、三四行……为一格。于是可以将 \(n\times n\) 的图形大概地分成两个 \(n/2\times n/2\) 的图形,总操作次数在 \(4\log n\) 级别,这是过不了的。

    观察数据范围,我们发现 \(\text{C}(Q/2,6)>n/2\),这意味着如果用 \(1\) 的个数为 \(6\) 个的十三位二进制数给行列重标号是完全足够的!二进制 \(1\) 的个数相等的数字有什么用呢?这意味着,如果数字 \(x,y\) 不同,那么一定存在一个二进制位 \(k\),满足 \(x\) 的第 \(k\) 位为零,\(y\) 的第 \(k\) 位为 \(1\)。也就是说,我们不再用讨论行列的 \(0,1\) 情况了。于是操作数正好是 \(2\times 13=26\).

    Code

    # include <cstdio>
    # include <cctype>
    # define print(x,y) write(x), putchar(y)
    
    template <class T>
    inline T read(const T sample) {
        T x=0; char s; bool f=0;
        while(!isdigit(s=getchar())) f|=(s=='-');
        for(; isdigit(s); s=getchar()) x=(x<<1)+(x<<3)+(s^48);
        return f? -x: x;
    }
    template <class T>
    inline void write(T x) {
        static int writ[50], w_tp=0;
        if(x<0) putchar('-'), x=-x;
        do writ[++w_tp]=x-x/10*10, x/=10; while(x);
        while(putchar(writ[w_tp--]^48), w_tp);
    }
    
    # include <vector>
    # include <iostream>
    # include <algorithm>
    using namespace std;
    
    const int maxn = 1505;
    
    vector <int> vec[2];
    int n,Ref[maxn],bit,N,M,Bit,_bit;
    struct node { int x,y; } s[maxn];
    
    inline void handleTask(int delta) {
        for(int b=0;b<13;++b) if((bit>>b&1) && !(Bit>>b&1)) {
            vec[0].clear(); vec[1].clear(); 
            for(int i=1;i<=N;++i) if(!(Ref[i]>>b&1)) {
                if(s[i].x) vec[0].emplace_back(s[i].x);
                if(s[i].y) vec[0].emplace_back(s[i].y);
            }
            if(delta) vec[0].emplace_back(1);
            sort(vec[0].begin(),vec[0].end());
            vec[0].erase(unique(vec[0].begin(),vec[0].end()),vec[0].end());
            for(int i=1;i<=M;++i) if(Ref[i]>>b&1)
                vec[1].emplace_back((i<<1)-1+delta);
            printf("%d %d",int(vec[0].size()),int(vec[1].size()));
            for(int d=0;d<2;++d) for(const auto& i:vec[d]) 
                putchar(' '), write(i); puts("");
        }
    }
    
    int main() {
        n=read(9), read(9); int idx=0; Bit=(1<<13)-1;
        for(int i=0, lim=1<<13; i<lim; ++i)
            if(__builtin_popcount(i)==6) {
                Ref[++idx]=i, bit|=i, Bit&=i; 
                if(idx==(n+1>>1)) break;
                else _bit = bit;
            }
        idx=0; for(int i=0;i<13;++i)
            if((bit>>i&1) && !(Bit>>i&1)) ++ idx;
        (n&1)? swap(bit,_bit): void(); for(int i=0;i<13;++i)
            if((bit>>i&1) && !(Bit>>i&1)) ++ idx;
        print(idx,'\n');
        for(int j=1;j<=n;j+=2) 
            s[j+1>>1] = (node){j,j+1<=n? j+1: 0};
        (n&1)? swap(bit,_bit): void();
        N=M=n+1>>1; handleTask(0);
        for(int j=2;j<n;j+=2)
            s[j>>1] = (node){j,j+1};
        if(n&1) s[N=(n+1>>1)] = (node){1,0}, M=n>>1;
        else s[N=(n>>1)] = (node){n,0}, M=n>>1;
        (n&1)? swap(bit,_bit): void(); handleTask(1);
        return 0;
    }
    

    \(\cal T_2\)

    Description

    Solution

    Code

    
    

    \(\cal T_3\)

    Description

    Solution

    Code

    
    
  • 相关阅读:
    Tomcat完美配置多个HOST主机,域名,SSL
    SpringCloud(10)使用Spring Cloud OAuth2和JWT保护微服务
    SpringCloud(9)使用Spring Cloud OAuth2保护微服务系统
    SpringCloud(8)微服务监控Spring Boot Admin
    React介绍
    SpringMVC-拦截器
    VSCode + WSL 2 + Ruby环境搭建详解
    Python中排序的灵活使用
    Linux中的进程与线程
    PHP-Phalcon框架中的数据库操作
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/16328197.html
Copyright © 2020-2023  润新知