4.9 Codeforces Round #781 (Div. 2)和Educational Codeforces Round 126 (Rated for Div. 2) ab

目录

Codeforces Round #781

A

B

Educational Codeforces Round 126 (Rated for Div. 2) 

A

B


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的序列,你可以交换相同下标的两序列元素,求\sum (|an-an+1|+|bn-bn+1|)

的最小值。取交换和不交换的绝对值之和最小值即可

//#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;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值