首页 > 其他分享 >CF1630A And Matching 题解

CF1630A And Matching 题解

时间:2024-05-05 15:35:42浏览次数:18  
标签:... texttt 题解 CF1630A 取反 000 111 反数 Matching

题目描述

有 \(n\) 个数 \(0,1,2,\cdots,n-1\)。你需要把他们两两分组,使得每组两个数按位与的结果之和 \(=k\)。如果可能,请构造出一组可能的 \(\frac n2\) 个数对,否则输出 -1

保证 \(n\) 是 \(2\) 的幂,\(k\le n-1\)

思路

首先我们发现,\(n\) 是二的幂,所以按照二进制的角度看,这些数字从 \(\texttt{000...000}\) 到 \(\texttt{111...111}\) 全部都有。

我们分三种情况讨论:

  • \(k=0\):对于这种情况,我们把每一个数字和它取反后的结果与起来

    以二进制的角度看,就是:\((000\&111)=0,(001\&110)=0,(010\&101)=0,(011\&100)=0\)

  • \(1\le k \le n-2\):这种情况比较复杂,我们考虑使得其中一组答案为 \(k\),其他均为 \(0\),不难发现我们可以把 \(k\) 和 \(n-1\) 分为一组,由于 \(n=2^x\),因此 \(n-1\) 二进制位全部为 \(1\),所以这一组答案 \(=k\),然后剩下的按照取反分组(\(k\) 取反的结果和 \(0\)(\(n-1\) 取反的结果)分组)

  • \(k=n-1\):

    • \(n=2 或4\):暴力证明无解

    • \(n>4\):我们来模拟一下 \(n=8\) 的情况:

      概括就是:

      我们称一个数为另一个数的“反数”,当且仅当这两个数每个二进制位上的数都相反。

      我们称一个数为“孤立的数”,当且仅当这个数的反数已经和别的数组成一对。

      • 首先配对 \((n-2,n-1)\),结果为 \(\texttt{111...110}\),孤立的数:\(0(n-1的反数),1(n-2的反数)\)
      • 然后配对 \((n-3,1)\),结果为 \(\texttt{000...001}\),孤立的数:\(0,2(n-3的反数)\)​
      • 此时 \(ans=n-1\)。
      • 最后把所有数和其反数配对,结果均为 \(0\),再把两个孤立的数 \(0,2\) 配对,结果也为 \(0\)。

代码

#include <bits/stdc++.h>
using namespace std;

int n,k;
void Main()
{
    scanf("%d%d",&n,&k);
    if(k==0){
        for(int i=0;i<n/2;i++){
            printf("%d %d\n",i,(n-1)-i);
        }
    }else if(k<n-1){
        printf("%d %d\n",0,(n-1)-k);
        printf("%d %d\n",k,n-1);
        for(int i=1;i<n/2;i++){
            if(i!=k and (n-1)-i!=k) printf("%d %d\n",i,(n-1)-i);
        }
    }else{
        if(n<=4){
            puts("-1");
        }else{
            printf("%d %d\n",0,2);
            printf("%d %d\n",1,n-3);
            printf("%d %d\n",n-2,n-1);
            for(int i=3;i<n/2;i++){
                if(i!=k and (n-1)-i!=k) printf("%d %d\n",i,(n-1)-i);
            }
        }
    }
}

int T;
int main()
{
    scanf("%d",&T);
    while(T--){
        Main();
    }
    return 0;
}

标签:...,texttt,题解,CF1630A,取反,000,111,反数,Matching
From: https://www.cnblogs.com/Sundar-2022/p/18173524

相关文章

  • [SDOI2015] 星际战争 题解
    假如将所有激光武器放在一边,所有机器人放在一边,激光武器向它可以伤害的机器人连边,再加超级源/汇点,这就是一个网络流问题。考虑激光武器向机器人连的边容量无限,而机器人向超级汇点连的边容量为机器人的装甲值,而超级源点连向激光武器的边则是用时\(\times\)激光武器伤害。发现假......
  • CF729B Spotlights 题解
    题目简述给出一个$n$行$m$列的$01$矩阵,定义每个点的价值为上下左右四个方向有$1$的方向数,求所有为$0$的点的价值和。题目分析我们首先可以考虑暴力,但是发现是不行的。于是我们考虑动态规划。设$dp_{i,j,0/1/2/3}$分别表示$(i,j)$这个点上方,左方,下方,右方是否有$......
  • [SCOI2007] 蜥蜴 题解
    发现实际上就是在求有多少只蜥蜴能逃出来。发现可以将柱子拆成入点和出点两部分,自己的出点向别人的入点连边,自己的入点向自己的出点连边。最后再加一个超级源点\(S\),连接所有有蜥蜴的柱子入点;再加一个超级汇点\(T\),连接所有能够跳出地图的柱子。我们猛然发现:这个问题不就是求......
  • 题解:AT_abc352_C [ABC352C] Standing On The Shoulders
    考场憋了很久,最后代码贼短……理想状态下,直接全排列解决问题。但是,\(1\len\le2\times10^5\),明显TLE,试都不用试的。咋优化呢?其实,前面的巨人只负责“打地基”,作为“塔尖儿”的巨人有且仅有1个。而前面地基随便排列,地基高度(他们的和)都不会变。所以,我们只需要枚举塔尖即......
  • 牛客小白月赛92 题解
    牛客小白月赛92题解A.获得木头签到\((x\times4)/2\times4=x\times8\)#include<bits/stdc++.h>usingnamespacestd;#definefffirst#definesssecond#definepbpush_back#defineall(u)u.begin(),u.end()#defineendl'\n'#definedebug(x......
  • 牛客 215E 黄魔法师 题解
    Description给出\(n,k\),求一个长度为\(n\)的数组\(a\),满足有恰好\(k\)对数对\((i,j)(1\leqi<j\leqn)\)满足\(a_i+a_j\)为完全平方数。如果不存在,输出\(-1\)。linkSolution显然如果\(k>\binom{n}{2}\)就一定无解。构造时会发现肯定要尽量弄成相同的......
  • 题解【[ABC155F] Perils in Parallel】(未完成)
    题目链接两个常规转化:灯的坐标与区间坐标都很大,不妨将其离散化,转化为\(1\simn\)的点与\(1\simn\)的操作区间。对于一段区间取反,可以理解为对一段区间异或\(1\),转化为在异或差分数组上操作,即差分数组\(diff_i=a_i\bigoplusa_{i-1}\),区间\([l,r]\)异或\(1\)转化为差......
  • 5月3日模拟赛题解(李时珍的皮肤衣 , 马大嘴的废话 , SSY的队列 , 清理牛棚 , 历史の研究)
    T1李时珍的皮肤衣发现是二进制进位,所以直接快速幂即可。#include<bits/stdc++.h>#defineint__int128inlineintread(){charch=getchar();intx=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'......
  • 题解:ssy的队列
    题目链接题目描述SSY是班集体育委员,总喜欢把班级同学排成各种奇怪的队形,现在班级里有\(N\)个身高互不相同的同学,请你求出这\(N\)个人的所有排列中任意两个相邻同学的身高差均不为给定整数\(M\)的倍数的排列总数。输入格式共三行:第一行为\(N\)第二行为\(N\)个不同的......
  • P10064 [SNOI2024] 公交线路 题解
    弱化版:CF1827EBusRoutes。对于\(n=2\)的情况可以判掉,剩下的情况取一个度数大于一的点作为根。首先发现如果叶子间满足条件,那么整棵树也满足条件。考虑叶子间什么时候满足条件,记点\(x\)通过最多一条路径可以到达的所有点的集合为\(S_x\),则需满足\(\forallx,y\in\mathbf......