Codeforces Round #653 (Div. 3)
B
只有两种操作 \(*2\) 和 \(/6\)
满足这种情况的 \(n=2^a\times3^b\) 才能变成 \(1\)
第一步 把多余的 \(3\) 全部 \(\times2\) 变成 \(6\) 操作次数 \(b-a\)
这之后,\(2\) 和 \(3\) 的因子数量相等即 \(a+(b-a) == b\)
\(n = 2^{a+(b-a)}\times3^{b} \mod 6 == 0\)
第二步 用 \(/6\) 的方式把整个式子变成 \(1\) 操作次数 \(b\)
总共的操作次数即 \(b-a+b\)
代码中 \(cnt2==a,cnt3==b\)
#include <bits/stdc++.h>
using namespace std;
int main() {
int t,n;
cin >> t;
while(t --) {
cin >> n;
int cnt2 = 0,cnt3 = 0;
while(n % 2 == 0) {
n /= 2;
cnt2 ++;
}
while(n % 3 == 0) {
n /= 3;
cnt3 ++;
}
if(n == 1 && cnt2 <= cnt3) cout << cnt3 - cnt2 + cnt3 ;
else cout << -1;
cout << endl;
}
return 0;
}
D
对于这种取余的问题,首先把每个数字都 \(mod\) 一遍然后在余数上做分析
题目要求每个数字只能操作一遍,而且每次 \(x\) 的值都在自增,我们把这种自增看成 \(\mod k\) 下的循环
每个数字需要的操作次数是 \(k-x\mod k\) , 只要找到 \(\max \lbrace k-x\mod k \rbrace\) 即可把所有数字都操作完
但是对于相同的余数来说,第一次把其中一个余数变成 \(k\) 的倍数之后,其他余数还要变,就只能等下一次循环了
所以还要加上 \(k\times m[k-k\mod x]\) ,其中 \(m[]\) 是记录每个余数出现了多少次
综合来看,一起取最大值即可
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main() {
int t,n,k,x;
cin >> t;
while(t --) {
cin >> n >> k;
map<LL,LL> m;
LL ans = -1;
for(int i = 0;i < n; ++i) {
cin >> x;
int re = x % k;
if(re) ans = max(ans,k - re + k * m[k - re] ++);
}
cout << ans + 1 << endl;
}
return 0;
}
参考
E1
把所有书本分成四种
\(00,01,10,11\) 显然 \(00\) 不可能满足题目条件,我们不考虑
对于\(01,10\) 从小大到排序,然后两个加一起放进 \(11\) (转化)
最后对 \(11\) 排序,取前 \(k\) 个即可
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int main() {
int n,k;
cin >> n >> k;
vector<int> s,a,b;
int t,x,y;
for(int i = 0;i < n; ++i) {
cin >> t >> x >> y;
if(x && y) s.push_back(t);
else if(x) a.push_back(t);
else if(y) b.push_back(t);
}
sort(a.begin(),a.end());
sort(b.begin(),b.end());
for(int i = 0;i < min(a.size(),b.size()); ++i) {
s.push_back(a[i] + b[i]);
}
sort(s.begin(),s.end());
if(s.size() < k) cout << -1 << endl;
else {
LL ans = 0;
for(int i = 0;i < k; ++i) {
ans += s[i];
}
cout << ans << endl;
}
return 0;
}
参考