Codeforces Round #764 (Div. 3) C. Division by Two and Permutation 题解

C. Division by Two and Permutation

题目

You are given an array a consisting of n positive integers. You can perform operations on it.

In one operation you can replace any element of the array ai with ⌊ai/2⌋, that is, by an integer part of dividing ai by 2 (rounding down).

See if you can apply the operation some number of times (possible 0) to make the array a become a permutation of numbers from 1 to n —that is, so that it contains all numbers from 1 to n, each exactly once.

For example, if a=[1,8,25,2], n=4, then the answer is yes. You could do the following:

  1. Replace 8 with ⌊8/2⌋=4, then a=[1,4,25,2].
  2. Replace 25 with ⌊25/2⌋=12, then a=[1,4,12,2].
  3. Replace 12 with ⌊12/2⌋=6, then a=[1,4,6,2].
  4. Replace 6 with ⌊6/2⌋=3, then a=[1,4,3,2].

[Input]

The first line of input data contains an integer tt (1 ≤ t ≤ 10^4) —the number of test cases.

Each test case contains exactly two lines. The first one contains an integer nn (1 ≤ n ≤ 50), the second one contains integers a1,a2,…,an (1 ≤ ai ≤ 10^9).

[Output]

For each test case, output on a separate line:

  • YES if you can make the array a become a permutation of numbers from 1 to n,
  • NO otherwise.

You can output YES and NO in any case (for example, strings yEs, yes, Yes and YES will be recognized as a positive response).

【样例】

[Input]

6
4
1 8 25 2
2
1 1
9
9 8 3 4 2 7 1 5 6
3
8 2 1
4
24 7 16 7
5
22 6 22 4 22

[Output]

YES
NO
YES
NO
NO
YES

[Note]

The first test case is explained in the text of the problem statement.

In the second test case, it is not possible to get a permutation.

【思路】

解题的两个重点:

1. a[i] 需除以2的条件(循环的条件):

  • 输入的数 a[i] > n
  • 满足条件 a[i] <= n ,但 a[i] 重复出现

(直至 a[i] 在区间 [1,n] 内,循环结束)

2. 什么样的数据会出现结果“NO”?

当 a[i] 经过除以2的操作后变成 0 ,数组a必不能成为1到n的数字的排列组合。

【核心代码】

for (int i=1;i<=n;i++) { //遍历输入的数据
	while (a[i]>n||flag[a[i]]==1) {  //注意两判断条件的顺序
		a[i]/=2;
	}
    if (a[i]==0) { //当数据中出现 0 时,数组a必不能成为1到n的数字的排列组合
		break;
	}
	flag[a[i]]=1;  //记录符合条件的a[i]是否已经出现
} 

【注意】

循环中的判断条件 “a[i] > n” 与 “flag[a[i]] == 1” 不可对调,否则会数组越界(Runtime error)。

因为我们开的flag数组大小是55,而题目中的数据a[i]最大可以是1*10^9。

应该先判断a[i]是否大于n,若a[i]<=n,再继续用flag数组判断这个数是否已经存在。

正确的顺序:

 错误的顺序:

【完整AC代码】

#include <iostream>
#include <string.h>
#include <math.h>
#define ll long long
using namespace std;
ll a[55],flag[55];  //flag--实现记录功能
int main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);  
	int t; cin>>t;
	while (t--) {
		memset(flag,0,sizeof(flag));
		int n; cin>>n;
		int node=1;
		for (int i=1;i<=n;i++) cin>>a[i];
		for (int i=1;i<=n;i++) {
			while (a[i]>n||flag[a[i]]==1) {  //两判断条件不可对调
				a[i]/=2;
			}
			if (a[i]==0) {
				node=0;
				break;
			}
			flag[a[i]]=1;
		}
		if (node) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	} 
	return 0;
}

感谢你的阅读(❁´◡`❁)

有错误欢迎指出,一起进步鸭!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值