Codeforces-Mainak and Interesting Sequence(题解)

题意

给你设置好长度为n,这 n 个数加起来的和为 m,让你创造一个数组a; 还需要满足条件:在数组a中 任何小于 ai 的之前的数 异或和 为0

空序列的异或和为 0

题解

异或:不相同的时候为 1 ; 0^0 = 0, 1^1 = 0, 1^ 0 = 1, 0^1 = 1;

首先我们很容易想到一种使异或和为0的简单方法:偶数个相同的数进行异或,所以 一种方法就出来了:

n 为奇数的时候,n-1一定是偶数,这时候我们就维护前 n - 1 个数都为 1,然后第 n 个数字 就维护为 m - (n-1) 即可。这时候即满足 n 个数,也满足和为 m。

n 无非奇数或者偶数,讨论完 n 为奇数接下来就讨论n 为偶数

我们·的思路大概还是凑出偶数个相同的数,这样异或和就是0

n 为 偶数的时候,m又分为两种情况:1.m 为偶数,2. m为奇数

  1. m为偶数的时候,此时 n 和 m都为偶数

    很容易一种想法:将m均分为n份,这样就是 m / n 个相同的数了,他们只有一个空序列 ,而空序列的异或和为 0;

    但是这种是错误的,简单的例子 m = 6,n = 4 是不能整除的

    最后的数组之和不是 m。

    既然这种不行,但是我们可以发现 n 是个偶数,我们可以设一个x,肯定有 n = 2 + x;而且此时的 x 一定是个偶数,2也是偶数

    这样就分成了 x 个相等的数 加上 2个相等的数了,偶数个相同的数异或和一定是 0,这时候只用满足 分出的这些数之和是 m即可

    很简单的方法,我们先分出 x 个 1 , 再分出来两个 (m - x) / 2即可。

  2. m为奇数的时候,此时 m 为奇数,n 为偶数

    这个显然是不成立的,从 1 就可以看出,分出来 x 个 1 后,还有 2 个数,这两个数的和要是 奇数,因为 偶数+奇数才是奇数

    所以一个数为偶数,一个数为偶数。两个数肯定是不一样的,异或和的序列肯定不是 0。

    最后一种是最简单的,如果n大于m显然是不成立的,因为所有的ai>=1,如过n大于m ,数组和一定大于 m。

代码

#include<iostream>
using namespace std;
const int N = 1e5 + 5;
int t, n, m;

void init() {
	cin >> n >> m;
}

void solve() {
	// 三种情况
	// 1. n 大于 m 一定不成立
	if (n > m) {
		cout << "NO" << endl;
		return ;
	}
	// 2. n 为奇数:偶数个 1 加上 m - (n-1)
	if (n & 1) {
		cout << "YES" << endl;
		for (int i = 1; i <= n - 1; ++i) cout << "1 ";
		cout << m - n + 1 << endl;
		return ;
	}
	// 3. n 为偶数: 又分为两种情况
	// i. n 和 m 都为偶数时,
	if (!(n & 1) && !(m & 1)) {
		cout << "YES" << endl;
		int ans = (m - n + 2) >> 1;
		for (int i = 1; i <= n - 2; i++) cout << "1 ";
		cout << ans  << " ";
		cout << ans;

		     cout << endl;
		return ;
	}
	// ii. m 为奇数, 一定不成立
	// m如果为奇数,则n为偶数的时候,一定不成立
	if ( !(n & 1) && (m & 1)) {
		cout << "NO" << endl;
		return ;
	}

}

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	cin >> t;
	while (t--) {
		init();
		solve();
	}

	return 0;
}



  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值