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(贪心)

降智严重——nowcoder练习赛46&&codeforces #561 Div2

Codeforces Global Round 19