Codeforces Round 1006 (Div. 3)(部分题解)

A. New World, New Me, New Array

思路:这题挺简单的,在对k取绝对值后会更简单一点。

然后注意上取整。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

void solve()
{
    int n, k, p;
    cin >> n >> k >> p;
    k = abs(k);
    if (n*p < k) cout << -1 << endl;
    else {
        cout << (k+p-1)/p << endl;
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    
    return 0;
}

B. Having Been a Treasurer in the Past, I Help Goblins Deceive

思路:统计‘-’和‘_’的数量,‘-’会分在‘_’的两边,保证左右乘积最大,即尽可能平均分配。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

void solve()
{
    int n;
    string s;
    cin >> n;
    cin >> s;
    int n1 = count(s.begin(), s.end(), '-');
    int n2 = n-n1;
    if (n1 < 2 || n2 < 1) cout << 0 << endl;
    else {
        int cnt = n1/2;
        cout << cnt*(n1-cnt)*n2 << endl;
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    
    return 0;
}

C. Creating Keys for StORages Has Become My Main Skill

思路:我看了半天才看懂MEX(S)的意思,这里补充介绍一下,就是它的值为0到后第一个没在S集合里面的值,因此它的最大值不会超过n-1,所以我们要让它最大,就要从0开始枚举。这里代码(i&x)==i表示i的二进制数都包含在x中,一旦枚举到不满足,MEX值定了,所以我们可以为任何(i&x)==i的i值,显然0必定符合且简单,所以不满足就输出0,当枚举到最后一个数时,我们还要考虑前面所有的OR是否等于x,这里我们考虑到如果加上次i=n-1满足也可以输出该i,不满足我们就要输出一个能让其满足的数,即(num^x)可以帮缺少的二进制1都补上。(二进制)

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

void solve()
{
    int n, x;
    cin >> n >> x;
    int num = 0;
    for (int i = 0; i<n; i++){
        if (i == n-1){
            if ((i|num) == x){
                cout << i << endl;
            }
            else cout << (num^x) << endl;
            return ;
        }
        if ((i&x)==i){
            cout << i << " ";
            num |= i;
        }
        else{
            cout << 0 << " ";
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    
    return 0;
}

D. For Wizards, the Exam Is Easy, but I Couldn't Handle It

思路:这道题由于n的范围比较小,可以直接暴力做出来,对于一个位置,往后枚举比较。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

void solve()
{
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i<n; i++) cin >> a[i];
    int sum = 0;
    for (int i = 0; i<n; i++){
        for (int j = i+1; j<n; j++){
            sum += (a[i] > a[j]?1:0);
        }
    }
    int l = 0, r = 0;
    int ans = sum;
    for (int i = 0; i<n; i++){
        int cur = sum;
        for (int j = i+1; j<n; j++){
            cur -= (a[i] > a[j]?1:0);
            cur += (a[i] < a[j]?1:0);
            if (cur < ans){
                ans = cur;
                l = i;
                r = j;
            }
        }
    }
    cout << l+1 << " " << r+1 << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    
    return 0;
}

E. Do You Love Your Hero and His Two-Hit Multi-Target Attacks?

思路:首先看到有公式之类要想着化简或者转化,这里对公式化简为

\left | x_a-x_b \right |\left | y_a-y_b \right |=0

所以只要x轴相等或者y轴相等就可以为一对,我们可以指定一个轴,然后来满足此条件。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

void solve()
{
    int k;
    cin >> k;
    vector<array<int, 2>> ans;
    int x = 0, y = 0;
    while (k){
        x++;
        int s = 1;
        while (s*(s+1)/2 <= k) s++;
        k -= s*(s-1)/2;
        for (int i = 1; i<=s; i++){
            y++;
            ans.push_back({x, y});
        }
    }
    cout << ans.size() << endl;
    for (auto [x, y]:ans){
        cout << x << " " << y << endl;
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    
    return 0;
}

F. Goodbye, Banker Life

思路:B站的一些视频说这种类型的三角形是组合数,因此他们把此题当作了组合数,并用Lucas定理来做,这里简单地说一下为什么和组合数相似。

列出组合数的三角形:

它受影响的方式和该题的差不多,只是当1<j<i时,组合数是加(也就是我们常说的杨辉三角),而该题是异或,之后就只需要判断奇偶性来判断,而Lucas定理就是用来计算大数情况下组合数模素数的结果,这里我们将该素数设为2就可以来判断奇偶性。

AC代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;

ll n, m, mod;
ll fact[100001], inv[100001];
ll qpow(ll a, ll b){
    ll res = 1;
    while (b){
        if (b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}
ll C(ll n, ll m){
    if (n > m) return 0;
    return fact[m]*inv[n]%mod*inv[m-n]%mod;
}
ll Lucas(ll n, ll m){
    if (n == 0) return 1;
    return Lucas(n/mod, m/mod) * C(n%mod, m%mod) %mod;
}
void init(ll mod){
    fact[0] = 1;
    for (int i = 1; i<=mod; i++){
        fact[i] = fact[i-1] * i % mod;
    }
    inv[mod-1] = qpow(fact[mod-1], mod-2);
    for (int i = mod-2; i>=0; i--){
        inv[i] = inv[i+1] * (i+1) % mod;
    }
}
void solve()
{
    int n, k;
    cin >> n >> k;
    for (int i = 0; i<n; i++){
        cout << Lucas(i, n-1)*k << " \n"[i==n-1];
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    mod = 2;
    init(mod);
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    
    return 0;
}

榜单上大佬们的代码比较简单,是有一个结论,判断C_{i}^{j}是奇数,当且仅当(i&j)==j(i的二进制位完全包含j的二进制位,可以用Lucas定理推导)。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

void solve()
{
    int n, k;
    cin >> n >> k;
    for (int i = 0; i<n; i++){
        cout << (((n-1)&i) == i ? k : 0) << " \n"[i==n-1];
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wirepuller_king

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

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

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

打赏作者

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

抵扣说明:

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

余额充值