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