Codeforces Round #838 (Div. 2)ABCD

A. Divide and Conquer

题意:给定一个数组,求使这个数组中所有元素的和为偶数的次数;

可以对数组中元素x进行操作,使x=x/2;

预处理求出1到N偶数变基数需要的操作次数,奇数变偶数的操作次数;

若sum为奇数,就找到使数字改变奇偶的最小次数就行

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, t;
string a, b;
vector<int>dp(N),ou(N);
void slove()
{
	cin >> n;
	vector<int>a(n);
	int sum = 0; int ans = INT_MAX;
	int res = 0;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
		sum += a[i];
		if (a[i] % 2)
			ans = min(ans, dp[a[i]]);
		else if (a[i] != 0)
			ans = min(ans, ou[a[i]]);
	}
	if (sum % 2)
		cout << ans << endl;
	else
		cout << res<<endl;
}
int main() {
	cin >> t;
 
	for (int i = 0; 2 * i + 1 < N; i++)
	{
		dp[2 * i + 1] = dp[i] + 1;
		ou[2 * i] = ou[i] + 1;
	}
	while (t--)
		slove();
}

B.Make Array Good

排序后,使序号靠后的数字是前面数字的倍数

需要注意的是记录排序前,每个位置的原本的位置

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
#define ll long long 
int n, t;
string a, b;
vector<int>dp(N),ou(N);
void slove()
{
	cin >> n;
	vector<ll>a(n);
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
		
	}
	vector<int>ind(n);
	if (n == 1) { cout << 0 << '\n'; return; }
	iota(ind.begin(), ind.end(), 1);
	sort(ind.begin(), ind.end(), [&](int i, int j)
		{
			return a[i-1] < a[j-1];
		});
	sort(a.begin(), a.end());
	int p = 0;
	int j = 1;
	int st = a[0];
	vector<vector<int>>ans;

	while (j<n)
	{
		while (j<n&&st == a[j])
			j++;
		if (j == n)break;
		if (a[j] % st==0) { st = a[j]; j++; }
		else {
			int d= (a[j] / st + 1) * st-a[j];
			ans.push_back({ind[j],d});
			a[j] += d;
			st = a[j];
			j++;
			p++;
		}
	}
	cout << p << endl;
	for (auto& t : ans)
		cout << t[0] << " " << t[1] << endl;

}

int main() {
	cin >> t;
	while (t--)
		slove();
}

C.Binary Strings are Fun​​​​​

题意比较绕,拓展比较好理解,就不说了,

对于给定字符串第i位来说,要求,拓展后,总共2*i-1个字符中,至少有i个字符与第i位相同。

有点像众数的概念。

这题是动态规划

转移方程和解释放在代码里面

#include <bits/stdc++.h>
using namespace std;
long long  ans = 1;
int n; string a;
const int mod = 998244353;
void solve()
{
    ans =1;
    cin >> n;
    cin >> a;
 long long cnt = 1;
    for (int i = 1; i < n; i++)
    {
        if (a[i] == a[i - 1])cnt = 2 * cnt % mod;/*如果与前一位相同,i之前,拓展后有i-1个a[i-1]的方法有cnt种,那么在a[i]和a[i-1]间无论放0还是1,都可以满足要求。*/
        else cnt = 1;/*如果不同,那么在在i之前,拓展后至少有i-1个个a[i-1]那么此时,在a[i]和a[i-1]间不填入数字的话,至少有i-1个a[i-1],i-1个a[i](原本应该有2*i-1个,有一个没插入呢)那么此时a[i]和a[i-1]直接只能插入a[i]相同的值,所以cnt=1;*/
        ans += cnt;
        ans%=mod;
    }
    cout << ans << endl;
}
int main()
{
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

D.GCD Queries

给一个数字n,然后有一个长度为n的隐藏的数组,由0到n-1构成;

找出其中的0;

可以输出? pos1 pos2

然后接受一个pos1 和pos2 的最大公因数

注意0与x的最大公因数为x

方法:

由于最大公因数小于等于这两个数的本身,那么对于任意数字与一个数字的最大公因数一定小于0与这个数字的最大公因数

也就是找查询最大值的下标(代码里面很直观);

#include <bits/stdc++.h>
using namespace std;
long long  ans = 1;
int n; string a;
const int mod = 998244353;
void solve()
{
    cin >> n;
    int x = 1, y = 2;
    int g1, g2,ans;
    for (int i = 3; i <= n; i++)
    {
        cout << "? " << x << " " << i << endl;
        cin >> g1;

        cout << "? " << y << " " << i << endl;
        cin >> g2;
        if (g2 > g1)x = i;
        if (g1 > g2)y = i;
    }

    cout << "! " << x << " " << y << endl;
    cin >> ans;
}
int main()
{
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值