Codeforces Round #767 (Div. 2) A - F

A

  • 排序即可
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while(t--){
        int n, k;
        cin >> n >> k;
        vector<pair<int, int> > a(n);
        for(auto &i : a) cin >> i.first;
        for(auto &i : a) cin >> i.second;
        sort(a.begin(), a.end());
        for(auto i : a){
            if(k >= i.first) k += i.second;
        }
        cout << k << '\n';
    }
    return 0;
}

B

给你一个从 l l l r r r的连续序列,可以对这个序列进行 k k k次操作,每次操作可以选择两个数求乘积,得到结果放回原序列中,问能不能在 k k k次操作以内让这个序列任意两项的 g c d > 1 gcd>1 gcd>1

  • 因为数字连续,所以我们选择 2 2 2作为质因子,那么答案就是总的数字个数 − - 含有因子 2 2 2的数字个数,也就是 r − l + 1 − ( r 2 − l − 1 2 ) r-l+1-(\frac r 2-\frac{l-1}2) rl+1(2r2l1)
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while(t--){
        int l, r, k;
        cin >> l >> r >> k;
        if(l == r){
            if(l == 1) cout << "NO\n";
            else cout << "YES\n";
        }else{
            if(k >= r - l + 1 - (r / 2 - (l - 1) / 2)) cout << "YES\n";
            else cout << "NO\n";
        }
    }
    return 0;
}

C

给你一个数列,每次从中取出若干个数,求他们的 m e x mex mex并放入到 b b b数组中,并把原来的数删去,让你求出一个字典序最大的 b b b数组

  • 尽可能的让第一个数更大,找尽可能大的 m e x mex mex,用一个指针记录当前位置,消耗一个较大的数是没有影响的
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        vector<int> a(n), cnt(n + 1);
        for(int i=0;i<n;i++){
            cin >> a[i];
            cnt[a[i]] += 1;
        }
        vector<bool> f(n + 1);
        queue<int> q;
        int p = 0;
        while(p < n){
            int now = 0;
            while(cnt[now] > 0){
                now += 1;
            }
            int num = 0;
            while(num < now){
                cnt[a[p]] -= 1;
                if(!f[a[p]] && a[p] < now){
                    num += 1;
                    f[a[p]] = true;
                }
                p += 1;
            }
            if(now == 0) p += 1;
            for(int i=0;i<now;i++){
                f[i] = false;
            }
            q.push(now);
        }
        cout << q.size() << '\n';
        while(!q.empty()){
            cout << q.front() << ' ';
            q.pop();
        }
        cout << '\n';
    }
    return 0;
}

D

让你从 n n n个字符串里面找到若干字符串按照顺序拼接起来组成一个回文串,字符串长度都在3以内,问能不能拼出来

  • 显然如果字符串长度是1,那么它自己就是回文;如果字符串长度是2,那么可能和2或3两种情况构成回文;如果长度为3,那么可能和2和3两种情况构成回文,分别讨论即可
#include <bits/stdc++.h>

using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        bool ok = false;
        set<string> two, three;        
        for(int i=0;i<n;i++){
            string s;
            cin >> s;
            if(s.length() == 1) ok = true;
            else if(s.length() == 2){
                if(s[0] == s[1]) ok = true;
                else{
                    string ss = s;
                    reverse(ss.begin(), ss.end());
                    if(two.count(ss)) ok = true;
                    for(char i='a';i<='z';i++){
                        if(three.count(ss + i)) ok = true;
                    }
                    two.insert(s);
                }
            }else{
                if(s[0] == s[2]) ok = true;
                else{
                    string ss = s;
                    reverse(ss.begin(), ss.end());
                    ss.pop_back();
                    if(two.count(ss)) ok = true;
                    ss = s;
                    reverse(ss.begin(), ss.end());
                    if(three.count(ss)) ok = true;
                    three.insert(s);
                }
            }
        }
        cout << (ok ? "YES" : "NO") << '\n';
    }
    return 0;
}

E

给你一个 n × n n\times n n×n的矩阵 b b b b i , j b_{i,j} bi,j是由矩阵 a i , j a_{i,j} ai,j的上下左右四个数取异或和得到的,现在求 a a a矩阵的所有元素的异或和

  • 有一种很简单的方法,任意给定矩阵 a a a的第一行,然后根据矩阵 b b b,求出整个矩阵 a a a,然后计算即可
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        vector<vector<int> > a(n, vector<int>(n));
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cin >> a[i][j];
            }
        }
        vector<vector<int> > res(n, vector<int>(n));
        int ans = 0;
        for(int i=1;i<n;i++){
            for(int j=0;j<n;j++){
                res[i][j] = a[i - 1][j];
                if(j >= 1) res[i][j] ^= res[i - 1][j - 1];
                if(j < n - 1) res[i][j] ^= res[i - 1][j + 1];
                if(i >= 2) res[i][j] ^= res[i - 2][j];
                ans ^= res[i][j];
            }
        }
        cout << ans << '\n';
    }
    return 0;
}

F1

a l i c e alice alice b o b bob bob玩游戏,一共有 n n n个回合,起始成绩为 0 0 0,每次 a l i c e alice alice选择一个 [ 0 , k ] [0,k] [0,k]内的实数, b o b bob bob可以选择加上或者减去,他至少要加 m m m次,问最终的成绩期望

  • d p [ i ] [ j ] dp[i][j] dp[i][j]为前 i i i个回合选择 j j j次加法得到的成绩,那么显然有 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + k + d p [ i − 1 ] [ j ] − k = d p [ i − 1 ] [ j − 1 ] + d p [ i − 1 ] [ j ] dp[i][j]=dp[i-1][j-1]+k+dp[i-1][j]-k=dp[i-1][j-1]+dp[i-1][j] dp[i][j]=dp[i1][j1]+k+dp[i1][j]k=dp[i1][j1]+dp[i1][j]
  • 初始状态为 d p [ i ] [ i ] = i × k dp[i][i]=i\times k dp[i][i]=i×k
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll MOD = 1e9 + 7;
ll fastpow(ll base, ll power){
    ll ans = 1;
    while(power > 0){
        if(power & 1) ans = ans * base % MOD;
        base = base * base % MOD;
        power >>= 1;
    }
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    ll inv = fastpow(2, MOD - 2);
    while(t--){
        int n, m, k;
        cin >> n >> m >> k;
        vector<vector<ll> > dp(n + 1, vector<ll> (m + 1));
        for(int i=1;i<=m;i++){
            dp[i][i] = 1ll * i * k % MOD;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(i == j) continue;
                dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % MOD * inv % MOD;        
            }
        }
        cout << dp[n][m] << '\n';
    }
    return 0;
}

F2

  • 考虑从 d p [ i ] [ j ] dp[i][j] dp[i][j] d p [ n ] [ m ] dp[n][m] dp[n][m]的转移,相当于从 ( i , j ) (i,j) (i,j) ( n , m ) (n,m) (n,m)的路径数量,考虑每一行,我们已知的初始状态是 d p [ i ] [ i ] dp[i][i] dp[i][i],考虑从这个状态开始转移,但是 d p [ i ] [ i ] dp[i][i] dp[i][i]不能直接走到 d p [ i + 1 ] [ i + 1 ] dp[i+1][i+1] dp[i+1][i+1],所以控制第一步先让他到 d p [ i + 1 ] [ i ] dp[i+1][i] dp[i+1][i],然后就变成从 ( i + 1 , i ) (i+1,i) (i+1,i) ( n , m ) (n,m) (n,m)的路径数量,应该是 C n − i − 1 m − i C_{n-i-1}^{m-i} Cni1mi,因为每一次都会除以2,所以最终统计出答案还要除以 2 n − i 2^{n-i} 2ni
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll MOD = 1e9 + 7;
ll fastpow(ll base, ll power){
    ll ans = 1;
    while(power > 0){
        if(power & 1) ans = ans * base % MOD;
        base = base * base % MOD;
        power >>= 1;
    }
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    vector<ll> fac(1e6 + 5);
    fac[0] = 1ll;
    for(ll i=1;i<=1e6;i++){
        fac[i] = fac[i - 1] * i % MOD;
    }
    function<ll(ll, ll)> C = [&](ll n, ll m){
        if(n < m) return 0ll;
        return fac[n] * fastpow(fac[n - m], MOD - 2) % MOD * fastpow(fac[m], MOD - 2) % MOD;
    };
    int t;
    cin >> t;
    while(t--){
        ll n, m, k;
        cin >> n >> m >> k;
        ll ans = 0;
        if(n == m){
            cout << n * k % MOD << '\n';
            continue;
        }
        for(int i=1;i<=m;i++){
            ans += C(n - i - 1, m - i) * i % MOD * k % MOD * fastpow(fastpow(2ll, n - i), MOD - 2) % MOD;
            ans %= MOD;
        }
        cout << ans << '\n';
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值