Codeforces Round 871 (Div. 4)

发布时间 2023-05-08 20:04:06作者: PHarr

A. Love Story

#include<bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}


void solve(){
    string s;
    cin >> s;
    int res = 0;
    for( int i = 0 ; i < s.size() ; i ++ )
        res += s[i] != "codeforces"[i];
    cout << res <<"\n";
    return;
}

int32_t main() {
    for( int t = read() ; t ; t -- )
        solve();
    return 0;
}

B. Blank Space

#include<bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}


void solve(){
    int n = read() , res = 0 , cnt = 0;
    for( int x ; n ; n -- ){
        x = read();
        if( x == 1 ) cnt = 0;
        else cnt ++ , res = max( res , cnt );
    }
    printf("%lld\n" , res);
    return;
}

int32_t main() {
    for( int t = read() ; t ; t -- )
        solve();
    return 0;
}

C. Mr. Perfectly Fine

dp一下就好了

#include<bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}


void solve(){
    int n = read();
    vector<int> f( 4 , 1e18 ) , g;
    f[0] = 0;
    for( int x , y ; n ; n -- ){
        x = read() , y = read();
        if( y > 1 ) y -= 8;
        g = f;
        for( int i = 0; i < 4 ; i ++ )
            f[i|y] = min( f[i|y] , g[i] + x );
    }
    if( f[3] == 1e18 ) printf("-1\n");
    else printf("%lld\n" , f[3] );
    return;
}

int32_t main() {
    for( int t = read() ; t ; t -- )
        solve();
    return 0;
}

D. Gold Rush

只有当前的数字是三的倍数才可以分。最多可以分\(\log_3n\)次,为了避免重复的情况可以加一个记忆化

#include<bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int n , m , f = 0;

set<int> vis;

void dfs( int x ){
    if( f == 1 || x < m || vis.count(x) ) return;
    if( x == m ){
        f = 1;
        return;
    }
    if( x % 3 ) return;
    dfs( x / 3 ) , dfs( x / 3 * 2 );
    return;
}

void solve(){
    n = read() , m = read() , f = 0;
    dfs(n);
    cout << ( f ? "yes\n" : "no\n");
    return;
}

int32_t main() {
    for( int t = read() ; t ; t -- )
        solve();
    return 0;
}

E. The Lakes

就搜一下就好了吧。

#include<bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

constexpr int dx[] = { 0 , 0 , 1 , -1 };
constexpr int dy[] = { 1 , -1 , 0 , 0};


void solve(){
    int n = read() , m = read() , res = 0;
    vector<vector<int>> g(n+1,vector<int>(m+1 , 0));
    for(int i = 1 ; i <= n ; i ++ )
        for( int j = 1 ; j <= m ; j ++ )
            g[i][j] = read();
    vector<vector<bool>> vis( n+1 , vector<bool>(m+1 , 0) );
    for( int i = 1 ; i <= n ; i ++ )
        for( int j = 1 ; j <= m ; j ++ ){
            if( vis[i][j] || g[i][j] < 1 ) continue;
            int cnt = 0;
            queue<pair<int,int>> q;
            q.emplace( i , j );
            while( !q.empty() ){
                auto [x,y] = q.front();
                q.pop();
                if( vis[x][y] ) continue;
                vis[x][y] = 1 , cnt = cnt + g[x][y];
                for( int l = 0 , fx , fy ; l < 4 ; l ++ ){
                    fx = x + dx[l] , fy = y + dy[l];
                    if( fx < 1 || fy < 1 || fx > n || fy > m || g[fx][fy] < 1 || vis[fx][fy] ) continue;
                    q.emplace(fx , fy);
                }
            }
            res = max( res , cnt );
        }
    printf("%lld\n" , res );
    return;
}

int32_t main() {
    for( int t = read() ; t ; t -- )
        solve();
    return 0;
}

F. Forever Winter

因为题目保证了\(x>1,y>1\)所以度为 1 的点一定是叶子节点。从叶子点向内走一步就是第一次扩展的点,在走一步就是根节点。然后根据度数计算\(x,y\)

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 1e6 + 5, M = 1505;
int pos[M][M], px[N], py[N];

int sum(int x) {
    return x * (x + 1) * (x * 2 + 1) / 6;
}

void solve() {
    int n = read() , m = read();
    vector<vector<int>> g(n+1);
    for( int u , v ; m ; m -- ){
        u = read() , v = read();
        g[u].push_back(v) , g[v].push_back(u);
    }
    int x , y;
    for( int i = 1 ; i <= n ; i ++ ){
        if( g[i].size() != 1 ) continue;
        x = g[i].front();
        for( auto v : g[x] ){
            if( g[v].size() != 1 ) y = v;
        }
        x = g[x].size() - 1 , y = g[y].size();
        printf("%lld %lld\n" , y , x);
        break;
    }
}

int32_t main() {
    for (int t = read(); t; t--)
        solve();
    return 0;
}

G. Hits Different

一个比较简单的模拟。首先要知道\(1^2+2^2+3^2+\cdots+n^2=\frac{n(n-1)(2n-1)}{6}\)

所以只要计算出每一层的左右端点即可。

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 1e6 + 5, M = 1505;
int pos[M][M], px[N], py[N];

int sum(int x) {
    return x * (x + 1) * (x * 2 + 1) / 6;
}

void solve() {
    int n = read(), res = 0;
    for (int i = px[n], l = py[n], r = py[n]; i >= 1; i--) {
        res += sum(pos[i][r]) - sum(pos[i][l] - 1);
        l = max(1ll, l - 1), r = min(r, i - 1);
    }
    printf("%lld\n", res);
}

int32_t main() {
    for (int i = 1, t = 0; t <= 1e6; i++)
        for (int j = 1; j <= i && t <= 1e6; j++)
            t++, pos[i][j] = t, px[t] = i, py[t] = j;
    for (int t = read(); t; t--)
        solve();
    return 0;
}

H. Don't Blame Me

f[i][j]表示前 i 位的非空子序列凑出 j 的方案数。所以只要枚举每一个选或不选,再枚举每一个数的前一个数即可。但是注意的是\(f[i][j]\)无法表示全空的情况,但是又会有前 i 个只选a[i]的情况,这种情况无法从之前的状态转移得来,所以f[i][a[i]]要单独加 1

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read(){
    int x = 0 , f = 1 , ch = getchar();
    while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
    if( ch == '-' ) f = -1 , ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x * f;
}

const int mod = 1e9+7;

void solve(){
    int n = read() , k = read();
    vector<vector<int>> f( n+1 , vector<int>(64 , 0) );
    for( int i = 1 , x ; i <= n ; i ++ ) {
        x = read();
        f[i][x] ++;
        for( int j = 0 ; j < 64 ; j ++ )
            f[i][j] = ( f[i][j] + f[i-1][j] ) % mod;
        for( int j = 0 ; j < 64 ; j ++ )
            f[i][j&x] = ( f[i][j&x] + f[i-1][j] ) % mod;
    }
    int res = 0;
    for( int i = 0 ; i < 64 ; i ++){
        auto t = bitset<6>(i);
        if( t.count() == k ) res = ( res + f[n][i] ) % mod;
    }

    printf("%lld\n" , res );
}

int32_t main() {
    for( int t = read() ; t ; t -- ) 
        solve();
}