Codeforces Round 970 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是单调的并且相邻元素的差值也是单调的,即 对于 2inai1<ai 同时对于 2i<naiai1<ai+1ai ,给定边界 l r ,找到处于区间中的好数 组的最大长度
思路:很容易想到每次相邻元素的差值是从1慢慢增加可以让好数组的增长速度最小,即长度最大化
列出表达式 ai=a1+j=1i1j ,因此很容易知道长度是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 可以到达 pi ,同时给定01串A,有 Ai=0 ,i为黑色,反之为白色,求每个点可以到达的黑色点的个数
思路:看到 i=Pi 想到置换环,同时对于一个环中的下标,可以到达的黑色的点的个数一定的相同的(类似缩点?),因此我们考虑用并查集来维护

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(n2)
我们列表达式 i=1n(j=inai×aj) 化简为
i=1n(ai×j=inaj) 发现可以使用前缀和维护,同时总情况数通过 Cn2 来计算,同时求逆元
启发:看到乘积混合加法时,可以考虑同类项合并后用前缀和维护!!!
类似题目: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";
}   
posted @   nnnnakosuki  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示