目录
Educational Codeforces Round 126 (Rated for Div. 2)
Codeforces Round #781
A
题意,找出四个数abcd时其和为n,且ab的最大公因数等于cd的最小公倍数
既然对每个数都存在解,可以考虑特殊值,带入1,发现ab其中一个为1则最大公约数为1,cd全为1则最小公倍数为1,得到 1,n-3,1,1四个数
#include <iostream>
using namespace std;
int main()
{
int t,n;
cin >> t;
while (t--) {
cin >> n;
cout << "1 " << n - 3 << " 1 1" << '\n';
}
}
B
题意,对于一个序列,你每次可以进行两种操作
1.复制当前数组
2.将原数组的一个元素与拷贝数组交换
问最少进行多少次操作,会得到一个全元素相等的序列。
最好的方案就是选定一个数作为结果的数,将其他数全部转换为他。这个数当然是原序列中出现最多的数,这样才会得到最小操作。所以用桶统计一下出现次数最多的数,剩下的数即为需要交换的 次数。接下来解决复制的次数,与需要交换的次数相加即可。可以看到,如果原来出现次数为n,那么没完成目标序列之前每交换一轮,目标数出现的次数就乘二。
//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
using namespace std;
int n,p, t;
int arr[10000000];
int main()
{
ios::sync_with_stdio(false); cout.tie(NULL);
int a, b, c, d;
cin >> t;
while (t--) {
unordered_map <int, int>m;
int mx = 0;
cin >> n;
for (int j = 0; j < n; j++) {
cin >> arr[j];
m[arr[j]]++;
mx = max(mx, m[arr[j]]);
}
int s = n - mx;
n -= mx;
while (n > 0) {
n -= mx;
s++;
mx *= 2;
}
cout << s << endl;
}
return 0;
}
Educational Codeforces Round 126 (Rated for Div. 2)
A
题意,给定两个长度相等为n的序列,你可以交换相同下标的两序列元素,求
的最小值。取交换和不交换的绝对值之和最小值即可
//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
using namespace std;
int t, n;
int main()
{
ios::sync_with_stdio(false); cout.tie(NULL);
cin >> t;
while (t--) {
vector<int>a;
vector<int>b;
cin >> n;
for (int j = 0; j < n; j++) {
int p;
cin >> p;
a.push_back(p);
}
for (int j = 0; j < n; j++) {
int p;
cin >> p;
b.push_back(p);
}
ll sum = 0;
for (int j = 1; j < n; j++) {
ll t1 = abs(a[j] - a[j - 1]), t2 = abs(a[j] - b[j - 1]),
t3 = abs(b[j] - b[j - 1]), t4 = abs(b[j] - a[j - 1]);
sum += min(t1 + t3, t2 + t4);
}
cout << sum << endl;
}
return 0;
}
B
算是比之前更难的题了,首先看题目,对一个数n每次你有两种操作
1.n=(n+1)%32768
2.n=(2*n)%32768
问最少几次操作可以使n变成0
刚入手确实不太好想,这样看32768也就是2^15,而n可以变成原来的两倍,要使i%32768==0,也就是变成32768的倍数,最坏的情况就是自乘2,15次。所以从15次入手,最少操作不会超过15.
我们还可以先判断n里含有2的多少次方m,最少操作数也就是15-m,再考虑自增1的情况,自增1的次数还不能超过现在得到的最少操作数,所以枚举自增1需要的操作数和15-m次取最小值即可
//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
using namespace std;
int t = 1, n;
int m = 32768;
int judge(int k) {
int cnt = 0;
while (k % 2 == 0 && k != 0) {
k /= 2;
cnt++;
}
return 15-cnt;
}
int main()
{
ios::sync_with_stdio(false); cout.tie(NULL);
cin >> n;
for (int j = 0; j < n; j++) {
int a;
cin >> a;
if (a == 0) {
cout << 0 << " ";
continue;
}
int ans = judge(a);
for (int j = 1; j <= 15; j++) {
ans = min(judge(a + j)+j, ans);
}
cout << ans << " ";
}
return 0;
}