大概是说给定一个序列,经过至多n次操作之后(任选一个数组中的值,可以将其值加上一个小于改值的数),任选出两个值中的最大值都能被任选两个值的最小值给除尽。
#include <iostream>
#include <algorithm>
using namespace std;
void sovle()
{
int n;
scanf("%d", &n);
printf("%d\n", n);
for (int i = 1; i <= n; i++)
{
int x;
scanf("%d", &x);
long long ans = 2;
while (ans < x)
ans = ans * 2;
printf("%d %d\n", i, ans - x);
}
return;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
sovle();
return 0;
}
一开始想的是,使得序列中的每一个值都是最小值的倍数就行,写完之后发现不对劲,仔细想想了,应该是每一个值都得是最小值的幂次,这样就能保证数组中的所有值都能被除尽,写完之后发现可能会超过n次的限制,最后发现并不需要是序列元素的最小值,只要保证是二的幂次就可以了
大概是给定n个序列,经过m次操作(使当前的值x变为x/2)后,使得序列之和为偶数,求最小的操作数
#include <iostream>
using namespace std;
int a[100];
void sovle()
{
int n, ans = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
ans += a[i];
}
if (!(ans & 1))
{
cout << "0\n";
return;
}
int cnt = 1e7 + 10;
for (int i = 1; i <= n; i++)
{
int x = a[i], s = 0;
if (x & 1)
{
while ((x & 1) != 0)
{
x = x / 2;
s++;
}
}
else
{
while ((x & 1) != 1)
{
x = x / 2;
s++;
}
}
cnt = min(cnt, s);
}
printf("%d\n", cnt);
return;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
sovle();
return 0;
}
一开始是觉得操作偶数没有意义,改变偶数的值不会使得奇偶性发生变化,于是我觉得是找最小的奇数的二进制中1的个数(顺便贴一个),wa了一次之后突然发现可以选择偶数,于是变成了找最小的那个数变成1或0的次数(没意识到可以变成除此之外的数......) 又wa了一次发现是写暴力的......
下次一定先看看数据范围,数据范围小的我就嘎嘎写暴力
int fun(int n)
{
int cnt=0;
while (n)
{
n=n&(n-1);
cnt+=1;
}
return cnt;
}
再贴一个大牛的,是我写不来的简洁
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
int par = 0;
int mn = 1E9;
for (int i = 0; i < n; i++) {
std::cin >> a[i];
par ^= a[i] & 1;//&1的结果只有0或1 ^0会变成1 ^1会变成0 用来判断sum的奇偶性
int x = a[i], t = 0;
while (x % 2 == a[i] % 2) {//直到奇偶性发生变化
x /= 2;
t++;
}
mn = std::min(mn, t);
}
std::cout << (par ? mn : 0) << "\n";
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}