Codeforces Round 951 (Div. 2)补题(C, D)

Codeforces Round 951 (Div. 2)补题(C, D)

链接:Codeforces Round 951 (Div. 2)

C. Earning on Bets

题目:
在这里插入图片描述
样例:
在这里插入图片描述
解题思路:
题目输出描述中用说明如果有多个输出我们输出一个即可(没截出来,点cf链接看原题可以发现),既然他都这么说了那我们自己暴力找乘积非常大的一种情况,即原序列每个元素相乘,然后b序列的每个值 b n b_n bn 都相当于所得乘积除以对应的 a n a_n an, 接下来再判断乘积跟 b n b_n bn的sum值的大小,最后就发现爆longlong了(悲),既然爆 l o n g l o n g longlong longlong了,那我们在稍微思考一下如何减小数据量,然后我们就可以想到我们可以用最小公倍数来替代乘积,我们将乘积改为最小公倍数就能过了
再附上官方的题解:
在这里插入图片描述

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long

ll Lcm(ll a, ll b) {
    return (a * b) / __gcd(a, b);
}

void solve() {
    int n; cin >> n;
    vector<ll> k(n);
    vector<ll> ans(n);
    ll temp = 1; //储存乘积
    ll sum = 0;

    for (int i = 0; i < n; i++) {
        cin >> k[i];
        temp = Lcm(temp, k[i]);
    }

    for (int i = 0; i < n; i++) {
        ans[i] = temp / k[i];
        sum += ans[i];
    }
    if (temp > sum) {
        for (int i = 0; i < n; i++) {
            cout << ans[i] << ' ';
        }
        cout << '\n';
    } else {
        cout << -1 << '\n';
    }

}

int main () {
    ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0);
    int t; cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

D. Fixing a Binary String

题目:
在这里插入图片描述

解题思路:
我们可以先遍历一遍原序列a,判断是否满足条件

  • 满足条件,直接把整个序列进行操作即可,此时答案就是序列长度n
  • 如果不满足条件,我们需将数字进行交换,然后因为会反转序列,我们当前位置的数字肯定跟最末尾的数字进行拼接,此时我们可先判断一下末尾数字还需添加多少个数字,如果末尾数字本身就大于k了,那肯定不能再添加当前位置的数字了
  • 如果末尾数字数量不足k,能够拼接,根据当前数字的数量又有两种情况:
    • 当前数字数量不足k,我们这自己都不够呢,只有将当前位置往前的所有数字都拼到后面,期盼末尾的数字补上后正好满足条件
    • 当前数字数量大于k,我们这绰绰有余啊,咱有的是金山银山,看末尾数字差几个,我们前面就给他补几个,然后判断是否满足条件

示例图:
在这里插入图片描述
复盘:
这题自己想的时候一团乱麻,一想到pos的位置条件判断就头大,最后还是看大佬的博客才发现pos还可以跟末尾数字联系起来,自己写的时候还因为用cin读取数字把一整个数字都读到a[0]去了(真的难绷),看了大佬的代码才知道可以用% 1 l l d 1lld 1lld一个一个读取数字,以前这都只知道看做字符串来处理的,又学到东西了好吧
在此附上大佬博客链接:大佬题解(ps:虽然搜这场cf肯定就能看到就是了)

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll MAX = 1e5+9;

ll n, k;
ll a[MAX], b[MAX];

ll check(ll ans) { //检查交换后是否满足条件
	ll cnt = 1;
	ll temp = b[1];
	for (int i = 2; i <= n; i++) {
		if (b[i] == temp && cnt < k) cnt++;
		else if (b[i] != temp && cnt == k) {
			temp = b[i];
			cnt = 1;
		} else {
			return -1;
		}
	}
	return ans;
}

void solve() {
    cin >> n >> k;
	for (int i = 1; i <= n; i++) scanf("%1lld", &a[i]);//用%1lld一个一个读取数字

	ll pos = 0;
	ll cnt = 1; //记录相同数字个数
	ll temp = a[1]; //记录现在判断的数字

	for (int i = 2; i <= n; i++) {
		if (a[i] == temp && cnt < k) cnt++;
		else if (a[i] != temp && cnt == k) {
			temp = a[i];
			cnt = 1;
		} else {
			pos = i; //如果发现当前数字不满足k条件
			break;
		}
	}
	//如果原序列本身就满足k条件,则把所有数都进行操作仍满足
	if (pos == 0) {
		cout << n << '\n';
		return;
	}
	//如果当前数字因数量小于k而跳出,我们需要把[0,pos]的所有元素都通过操作到序列尾部,如何判断是否满足条件
	if (cnt != k) {
		for (int i = pos; i <= n; i++) {
			b[i-pos+1] = a[i];
		}
		for (int i = pos-1; i >= 1; i--) {
			b[n+1-i] = a[i];
		}
		cout << check(pos-1) << '\n';
		return;
	} 
	//如果当前数字因数量大于k而跳出,我们可以发现如果交换后满足k,当前数字肯定与序列尾的数字相等,我们判断序列尾还差几个元素即可
	ll same = 0;

	for (int i = n; i > 0; i--) {
		if (a[i] == a[pos-1]) same++;
		else break;
	}
	//如果序列尾的数字相等的数量大于k,则一定不满足
	if (same > k) {
		cout << -1 << '\n';
		return;
	}
	//现在pos是因大于k而跳出,然后末尾相同元素数量为same个,我们需把pos前移pos,然后交换构造序列b,判断是否满足条件
	pos -= same;
	for (int i = pos; i <= n; i++) {
		b[i-pos+1] = a[i];
	}
	for (int i = pos-1; i >= 1; i--) {
		b[n+1-i] = a[i];
	}
	cout << check(pos-1) << '\n';

}

int main () {
    // ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0);
    int t; cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}
  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值