数组变换(通过乘2将所有数变相等)
题目链接:数组变换__牛客网
原题复现
牛牛有一个数组,里面的数可能不相等,现在他想把数组变为:所有的数都相等。问是否可行。
牛牛可以进行的操作是:将数组中的任意一个数改为这个数的两倍。
这个操作的使用次数不限,也可以不使用,并且可以对同一个位置使用多次。
数据范围:数组大小满足 1≤n≤50,数组中的数满足 1≤val≤10^9
输入描述:
输入一个正整数N (N <= 50)
接下来一行输入N个正整数,每个数均小于等于1e9.
输出描述:
假如经过若干次操作可以使得N个数都相等,那么输出"YES", 否则输出"NO"
示例:
输入
2
1 2
输出
YES
思路剖析
-
首先,我们假设这n个数经过变换满足所有数相等,考虑到既然每个数都进行了不同次数的乘2操作,那么最终得到的数肯定可以整除原数组中的每一个数,也可以被2所整除。
-
如果要使得他们在经历不同次乘2操作后值相等,那么初始数组中最小的数一定可以被其他所有数整除(或最大的数一定可以整除其他所有数)。因为如果最小数与其他数之间没有因数关系,那么最小数与其他数经过不同的2^n运算是始终无法相等的。如果每个数都满足该条件,那么最小数即为其他所有数的公共因数,可以进入下一步判断,否则判否。
-
检查数组中是否存在某个数e,使得 e/minval 为奇数。因为一旦最小数和某个数之间的倍数关系为非偶数,那么两者之间的转换倍数必定不可表示为2的n次方。这里考虑到c中的 ‘/’ 运算符,对于正数之间的运算存在向下取整,例如 3/2 = 1,但是只要发生取整转换,说明 e 和 minval 之间不满足整数倍关系,唯有通过条件 (2) 才能执行到这里,故此情况不存在。另外,由于避免数组中遍历到的值e和minval值相等,本来这轮遍历是满足条件的,但是 e/minval 的值是1 非偶数,所以对于 e/minval 计算到的值判断是否为偶数前先要保证它不等于1。(避免e和minval同值情况的误判)
-
数组中所有数都满足 (2)、(3) 的两个判断条件,那么返回true打印"YES",否则打印"No"。
示例代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n = 0;
cin >> n;
vector<int> v(n, 0);
int minval = 1e9;
bool flag = true;
for(auto& e: v)
{
cin >> e;
minval = min(e, minval);
}
for(auto e: v)
{
// 1.首先检查是否有元素不能被 min_val 整除
if(e % minval != 0)
{
flag = false;
break;
}
// 2.检查数组中是否存在e,使得e/minval为非偶数且不为1
int x = e / minval;
if(x != 1 && x % 2 != 0) { flag = false; break;}
}
if(flag)
{
cout << "YES" << endl;
}
else{
cout << "NO" << endl;
}
}