首页 > 其他分享 >Codeforces Round 970 div3

Codeforces Round 970 div3

时间:2024-09-02 22:39:06浏览次数:3  
标签:std 970 int com codeforces Codeforces https problem div3

Codeforces Round 970 div3

错过的一场比赛,第二天早晨VP,题目的通过率还挺奇怪


A. Sakurako's Exam

https://codeforces.com/contest/2008/problem/A

题意:有a个1和b个2的数组,在1和2前面增添加减号,判断是否能让结果为0
思路:1个2需要2个1进行填补,不如先让2自己进行消去,如果剩一个2再判断是否能拿两个1进行消去,之后看剩余的1是否能自己消去

void solve() {
    int a,b;
    std::cin >> a >> b;
    b %= 2;
    if(b != 0 && a >= 2 * b) {
        a -= 2 * b;
        b = 0;
    }
    if(a % 2 == 0 && !b) std::cout << "YES" << "\n";
    else std::cout << "NO\n";
}   

B. Square or Not

https://codeforces.com/contest/2008/problem/B

题意:对于一个给定的01串,判断元素受否能依次填充到一个正方形矩阵中同时矩阵的边缘为1内部为0(这里用的手动开根,防止精度 问题)
思路:先判断串的长度是否是完全平方数再直接暴力模拟

int rsqrt(int x) {
    int l = 0,r = 500;
    while(l < r) {
        int mid = (l + r + 1) >> 1;
        if(mid * mid <= x) l = mid;
        else r = mid - 1;
    }
    return l;
}
void solve() {
    int n;
    char a[N][N];
    std::string str;
    std::cin >> n;
    std::cin >> str; 
    if(rsqrt(n) * rsqrt(n) != n) std::cout << "No\n";
    else {
        int t = rsqrt(n);
        for(int i = 1;i <= t;i ++ )
            for(int j = 1;j <= t;j ++ ) {
                a[i][j] = str[(i - 1) * t + j - 1];
            }
        bool ok = true;
        for(int i = 1;i <= t;i ++ )
            for(int j = 1;j <= t;j ++ ) {
                if((i == 1 || i == t || j == 1 || j == t) && a[i][j] == '0') ok = false;
                if(!((i == 1 || i == t || j == 1 || j == t)) && a[i][j] == '1') ok = false;
            }
        std::cout << (ok ? "Yes" : "No") << "\n";
    }
}   

C. Longest Good Array

https://codeforces.com/contest/2008/problem/C

题意:好数组的定义:数组a是单调的并且相邻元素的差值也是单调的,即 对于 $ 2 \leq i \leq n $ 有 $ a_{i - 1} < a_{i} $ 同时对于 $ 2 \leq i < n $ 有 $ a_i - a_{i - 1} < a_{i + 1} - a_i $ ,给定边界 $ l $ $ r $ ,找到处于区间中的好数 组的最大长度
思路:很容易想到每次相邻元素的差值是从1慢慢增加可以让好数组的增长速度最小,即长度最大化
列出表达式 $ a_i = a_1 + \sum\limits_{j = 1}^{i - 1}j$ ,因此很容易知道长度是i可以取到的最大值,这里具有明显的单调性,可以直接二分解决

void solve() {
    std::cin >> x >> y;
    int l = 0,r = 44722;
    while(l < r) {
        int mid = (l + r + 1) >> 1;
        if(x + mid * (mid + 1) / 2 <= y) l = mid;
        else r = mid - 1;
    }
    std::cout << l + 1 << "\n";
}   

D. Sakurako's Hobby

https://codeforces.com/contest/2008/problem/D

题意:给定一个排列P,有 \(i\) 可以到达 \(p_i\) ,同时给定01串A,有 \(A_i = '0'\) ,i为黑色,反之为白色,求每个点可以到达的黑色点的个数
思路:看到 \(i = P_i\) 想到置换环,同时对于一个环中的下标,可以到达的黑色的点的个数一定的相同的(类似缩点?),因此我们考虑用并查集来维护

int find(int x) {
    return (f[x] == x ? f[x] : find(f[x]));
}
void bfs(int x) {
    std::queue<int> q;
    ok[x] = true;
    q.push(x);
    while(!q.empty()) {
        int t = q.front();
        q.pop();
        for(auto i : e[t]) {
            if(ok[i]) continue;
            ok[i] = true;
            f[find(i)] = find(t);
            if(a[i] == '0') size[find(t)] += 1;
            q.push(i);
        }
    }
}
void init() {
    for(int i = 0;i <= n;i ++ ) {
        e[i].clear();
        f[i] = i;
        ok[i] = false;
    }
}
void solve() {
    std::cin >> n;
    init();
    for(int i = 1;i <= n;i ++ ) {
        int x;
        std::cin >> x;
        e[i].push_back(x);
    }
    std::cin >> a;
    a = " " + a;
    for(int i = 1;i <= n;i ++ ) {
        size[i] = 0;
        if(a[i] == '0') size[i] = 1;
    }
    for(int i = 1;i <= n;i ++ ) {
        if(!ok[i]) bfs(i);
    }
    for(int i = 1;i <= n;i ++ )
        std::cout << size[find(i)] << " \n"[i == n];
}   

F. Sakurako's Box

https://codeforces.com/contest/2008/problem/F

题意:计算盒子中任意选择两个球价值相乘的期望
思路:即计算盒子所有可能的球价值乘积再求和,最后除总的情况数,看似是 $ O(n^2) $
我们列表达式 \(\sum\limits_{i=1}^n(\sum\limits_{j=i}^n{a_i \times a_j})\) 化简为
\(\sum\limits_{i=1}^n(a_i \times \sum\limits_{j=i}^na_j)\) 发现可以使用前缀和维护,同时总情况数通过 \(C^2_n\) 来计算,同时求逆元
启发:看到乘积混合加法时,可以考虑同类项合并后用前缀和维护!!!
类似题目:https://codeforces.com/problemset/problem/1996/E

int quickPow(int a,int b) {
    int res = 1;
    while(b) {
        if(b & 1) res = res * a % Mod;
        a = a * a % Mod;
        b >>= 1;
    }
    return res;
}
void init() {
    fact[0] = 1,infact[0] = 1;
    s[0] = 0,a[0] = 0;
    for(int i = 1;i <= n;i ++ ) {
        s[i] = 0;
        a[i] = 0;
        fact[i] = (fact[i - 1] % Mod * (i % Mod)) % Mod;
        infact[i] = quickPow(fact[i],Mod - 2);
    }
}
int C(int n,int m) {
    return ((fact[n] * infact[n - m]) % Mod * infact[m]) % Mod;
}
void solve() {
    std::cin >> n;
    init();
    for(int i = 1;i <= n;i ++ ) {
        std::cin >> a[i];
        s[i] = (s[i - 1] + a[i] % Mod) % Mod;
    }
    int P = 0;
    for(int i = 1;i <= n;i ++ ) {
        int x = (s[n] - s[i] + Mod) % Mod;
        P = ( P + a[i] % Mod * x ) % Mod;
    }
    int Q = quickPow(C(n,2),Mod - 2);
    int ans = (P * Q) % Mod;
    std::cout << ans << "\n";
}   

标签:std,970,int,com,codeforces,Codeforces,https,problem,div3
From: https://www.cnblogs.com/LZzzJ/p/18393604

相关文章

  • Codeforces Round 969 Div.2+Div.1
    A.Dora'sSet注意到任意两个偶数的\(\gcd\)都大于\(1\),因此选择的三个数中至多一个偶数,而注意到相邻的奇数一定互质,因此每次选两个奇数一个偶数,答案=奇数的个数÷2点击查看代码#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#defineullunsigned......
  • codeforces做题记录(1924B)& 回顾线段树
    1924B.SpaceHarbour题意:n个点排成一行,其中某些点上面建有港湾,港湾有一个权值,对每个点我们定义点的权值为“左边(包括自己)第一个港湾上的权值\(\times\)到右边(包括自己)第一个港湾的距离”(保证在一开始1号和n号点上都有港湾)。有q次操作:操作1给定x和v,表示在x点上建立权值为v的......
  • Codeforces Round 969 (Div. 2)
    ab题没啥好说的,b题一开始看题错成线段树了,后面发现维护最大值就过了(我就说b怎么会有线段树)。。。C:DoraandC++卡的我死死的,好久没卡c了,数论果然是最短板。。。我有两个推论,但是一个都不会用:1.翡蜀定理。(但是这题只有正数)(处理两个数的情况)2.断环为链。(但是我只会n方,即以每个......
  • codeforces写题随录 ##1
    菜鸡刷题比赛日记之数学知识相关[https://codeforces.com/contest/2007/problem/C](C.DoraandC++)这题包含加A和加B,此处应该先考虑特殊情况a=b,若不进行如何操作的话,初始答案应该是res=a[n]-a[1](排序之后),然后进行操作,想想该如何最小化极差。为了便于计算,先将数组中每个数字......
  • Codeforces Round 873 (Div. 2)
    ABC都很简单,但是D1写起来有些麻烦,就没写,D2应该是一个分治的思路,后面想不出来了。D1的思路非常好出,n只有5e3的范围,意味着\((n^2)\)可过,可以直接枚举所有的子区间,也就是题目所说的子数组,然后尝试统计答案。考虑一个子区间的答案是什么样的,发现只有逆序的数字才需要排序,我们直接找......
  • Educational Codeforces Round 169 (Rated for Div. 2)
    A.ClosestPoint有解的情况,当且仅当只有两个点且不相邻是,把新加入的点放在中间。#include<bits/stdc++.h>usingnamespacestd;usingi32=int32_t;usingi64=longlong;usingi128=__int128;#defineinti64usingvi=vector<int>;usingpii=pair<int,int......
  • codeforces做题记录(1942D,1938J,1934D1,1933F)
    1942D.LearningtoPaint题目大意:给定一行白格子,可以将任意的格子染成黑色,最终形成多个黑色的连续段,对每个连续段[i,j]有一个权重(题目给定),为aij,每个染色方案的权值就是所有连续段的权值的和。要求所有染色方案中前k大的权值。注意事项:权重aij的范围是[-1e6,1e6],格子个数n<=10......
  • Codeforces Round 966 (Div. 3)
    A.PrimaryTaskif-else语句练习,判断前两个字符是否为"10",并判断之后的字符是否大于1点击查看代码#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#defineullunsignedlonglong#definepiipair<int,int>intread(){intx=0,f=0;ch......
  • Educational Codeforces Round 169 (Rated for Div. 2)
    A.ClosestPoint两个数时只要不相邻就有解,超过两个数无解点击查看代码#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#defineullunsignedlonglong#definepiipair<int,int>intread(){intx=0,f=0;charc=getchar();whi......
  • Codeforces Round 968 (Div. 2)
    题目链接:CodeforcesRound968(Div.2)-Codeforces总结:C题想到了,但是写成shi了,出得有点慢。A.TurtleandGoodStringtag:签到Solution:直接判断第一个字符是否与最后一个字符相等即可。voidsolve(){cin>>n;strings;cin>>s;if(s[0]==s[n-1]......