Codeforces Round #561 (Div. 2) 题解
Posted heyuhhh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #561 (Div. 2) 题解相关的知识,希望对你有一定的参考价值。
Codeforces Round #561 (Div. 2) 题解
A. Silent Classroom
水题。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 105;
int n;
char s[N], t[N];
int main() {
cin >> n;
for(int i = 1; i <= n; i++) {
scanf("%s", t + 1);
s[i] = t[1] ;
}
sort(s + 1, s + n + 1) ;
int cnt = 0;
int ans = 0;
for(int i = 1; i <= n + 1; i++) {
if(s[i] != s[i - 1]) {
if(cnt == 0) cnt = 1;
else {
int tmp = cnt / 2;
ans += tmp * (tmp - 1) / 2 + (cnt - tmp) * (cnt - tmp - 1) / 2;
cnt = 1;
}
} else cnt++;
}
cout << ans ;
return 0;
}
B. All the Vowels Please
满足行列都大于5就行了,后面乱构造一下就好了。
代码如下:
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 105;
int n;
char s[N] = {'0', 'a', 'e', 'i', 'o', 'u'} ;
int main() {
cin >> n;
int r, c = -1;
for(int i = 5; i < n; i++) {
if(n % i == 0 && n / i >= 5) {
r = i;
c = n / i;
break ;
}
}
if(c == -1) {
cout << -1;
return 0;
}
for(int i = 1; i <= r; i++) {
int k = (i - 1) % 5 + 1;
for(int j = 1; j <= c; j++) {
cout << s[(j + k - 2) % 5 + 1] ;
}
}
return 0;
}
C. A Tale of Two Lands
比赛时硬生生分情况讨论...最后可能是因为细节原因还是没有A出来。好吧傻逼了。
对于\(|x|,|y|\)来说,\(x,y\)的正负并不会产生什么影响;对于\(|x-y|,|x+y|\)来说,\(x,y\)的正负也不会产生什么影响。所以我们就可以直接对\(a_i\)取绝对值,只看为正数的情况就好了。
然后就随便推一下,把绝对值去掉就行了。
代码如下:
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
int n;
ll a[N], b[N];
int main() {
ios::sync_with_stdio(false); cin.tie(0) ;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i], b[i] = a[i] < 0 ? -a[i] : a[i] ;
sort(b + 1, b + n + 1) ;
ll ans = 0;
int l = 1, r = 2;
while(r <= n) {
while(l < r && b[l] * 2 < b[r]) l++;
ans += r - l;
r++;
}
cout << ans;
return 0;
}
D. Cute Sequences
这个题上午把我整自闭了...还是细节方面没有处理好。
首先可以推出\(x_n=2^{n-2}*a+2^{n-3}*r_2+\cdots+2*r_{n-2}+r_{n-1}+r_n\),因为\(1\leq r\leq m\),我们可以知道如果存在一个\(n\)满足条件,那么有\(2^{n-2}*(a+1)\leq b\leq 2^{n-2}*(a+m)\),通过这个来判断是否存在合理情况就行了。我一开始判断这里的时候爆long long了。。。也搞了我半天。
之后我们就开始构造方案,首项为\(a\),我们先令\(r_i=1\),那么此时最大项的值就为\(2^{n-2}*(a+1)\),现在要做的就是改变某些\(r_i\)的值,使得最后最大项等于\(b\)。
令\(R=b-2^{n-2}*(a+1)\),根据我们之前推出来的式子,可以知道\(r_i\)之前的系数为\(2^{n-i-1}\),贪心来构造的话就是每次找到一个最大的\(X\),满足\(X*2^{n-i-1}\leq R 且 (X+1)*2^{n-i+1}>R\),并且\(1\leq X\leq m\),然后每次令\(r_i\)等于\(X\)即可。
这样来构造的话最后是肯定保证有解的。
代码如下:
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 105;
const ll MAX = 1e14 ;
ll q, a, b, m;
ll r[N] ;
ll qp(ll A, ll B) {
ll ans = 1;
while(B) {
if(B & 1) ans = ans * A;
A = A * A;
B >>= 1;
}
return ans ;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0) ;
cin >> q;
while(q--) {
memset(r, 0, sizeof(r)) ;
cin >> a >> b >> m;
if(a == b) {
cout << 1 << ' ' << a << '\n' ;
continue ;
}
int p = -1;
for(int i = 2; i <= 50; i++) {
if(qp(2, i - 2) * (a + 1) > MAX) break ;
if(qp(2, i - 2) * (a + 1) <= b && qp(2, i - 2) * (a + m) >= b) {
p = i;
break ;
}
}
if(p == -1) {
cout << -1 << '\n';
continue ;
}
ll R = b - qp(2, p - 2) * (a + 1);
ll S = a;
for(int i = 2; i < p; i++) {
ll now = qp(2, p - i - 1) ;
ll x = min(R / now, m - 1) ;
r[i] = x;
}
S = a;
cout << p << ' ' << S << ' ';
for(int i = 2; i < p; i++) {
cout << S + r[i] + 1 << ' ' ;
S += S + r[i] + 1;
}
cout << b << '\n' ;
}
return 0;
}
E. The LCMs Must be Large
这是个很有意思的题。首先很容易证明如果存在两天,在这两天中得到的数字集合不存在交集,那么肯定是无解的。
主要就是证明两两天数之间存在交集时,为什么一定方案有解。
可以这样来构造,如果在第\(j\)天去了\(\{a_1,a_2,\cdots,a_k\}\)这些商店,那么我们将这些位置的数都乘以第\(j\)个质数。
最后如果两两天数之间存在交集的话,那么它们的lcm肯定为所有质数的乘积,而它们补集的lcm肯定不存在当前天的质数。
所以这种构造方案就可以保证任意两天存在交集时是一定有解的。
由于\(m\)的范围很小,所以求是否有交时暴力一下就行了。
代码如下:
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 55, N = 1e4 + 5;
int m, n;
int s[N] ;
vector <int> v1[N], v2[M] ;
bool vis[M] ;
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> m >> n;
for(int i = 1; i <= m; i++) {
int x, y;
cin >> x;
for(int j = 1; j <= x; j++) {
cin >> y;
v1[y].push_back(i) ;
v2[i].push_back(y) ;
}
}
int ok = 1;
for(int i = 1; i <= m; i++) {
memset(vis, 0, sizeof(vis)) ;
int cnt = 0;
for(auto other : v2[i]) {
for(auto v : v1[other]) {
if(!vis[v]) vis[v] = 1, cnt++;
}
}
if(cnt < m) {
ok = 0;
break ;
}
}
if(ok) cout << "possible" ;
else cout << "impossible";
return 0;
}
以上是关于Codeforces Round #561 (Div. 2) 题解的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #561 (Div. 2) (还差2题)
Codeforces Round #436 E. Fire(背包dp+输出路径)
[ACM]Codeforces Round #534 (Div. 2)
Codeforces Round #726 (Div. 2) B. Bad Boy(贪心)