跳转至

第 49 届 ICPC 国际大学生程序设计竞赛邀请赛武汉站

2025-04-20

去年其实VP过一次,但是没啥写的,而且也想再试下这个。也还行吧,第四个其实想不到也正常,看了题解。

B 去年居然为WA了 3 个小时。。。且最后也没对,现在看来确实只是个位运算的很简单的题目。

B

简单来说就是构造 \(n\) 个非负整数,使得它们的和为 \(sum\) ,且按位或的值最小,简单的贪心一下就好了。还是有一点点细节要注意的,这次还WA了两次,去年也是这里。

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

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n;
    cin >> n;
    ll sum = 0;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        sum += x;
    }
    // cerr<<(1LL<<30);
    // cerr << sum << '\n';
    ll res = 0;
    for (int i = 30; i >= 0; i--)
    {
        ll val = ((1LL << i) - 1) * n;
        if (val >= sum)
            continue;
        if (sum >= (1LL << i) * n)
            sum -= (1LL << i) * n;
        else
            sum %= (1LL << i);
        res |= 1LL << i;
    } // 1001
    cout << res << '\n';
    return 0;
}

F

二分那个数字的值,没问题,但是再怎么搞呢?我倒是看出来了前 \(k\) 小的数会被圈在右上角。且每列的长度是小于等于左边一列的长度,每行也是类似的,但是没想到这个怎么处理。

若是再对每行进行二分,则总共需要 \(n\log n \log n^2\) 次操作,显然不太行。

没想到阿,题解里它是假设开始是 \(r,c\) 位置,若 \(\le x\) ,则检查 \(r,c+1\) ,否则检查 \(r-1,c\) ,则总次数最多 \(2n\log n^2\) ,刚好够用。

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

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n,k;
    cin>>n>>k;
    k=n*n-k+1;
    auto ask=[&](int i,int j,int x){
        cout<<"? "<<i<<" "<<j<<" "<<x<<endl;
        int res; cin >> res;
        return res;
    };
    auto check=[&](int x){
        int r=n,c=1,cnt=0;
        while(r>0&&c<=n){
            if(ask(r,c,x)) cnt+=r,c++;
            else r--;
        }
        return cnt>=k;
    };
    int lo=0,hi=n*n+1;
    while(lo<hi-1){
        int mid=(lo+hi)>>1;
        if(check(mid)) hi=mid;
        else lo=mid;
        // cerr<<lo<<" "<<hi<<endl;
    }
    cout<<"! "<<hi<<endl;
    return 0;
}

I

简单找规律

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

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    string s;
    cin>>s;
    int cnt=0;
    if(s[0]=='1') cnt++;
    for(int i=1;i<s.size();i++){
        if(s[i]=='1'&&s[i-1]=='0')  cnt++;
    }
    if(cnt==0) cout<<cnt<<'\n';
    else if(s.back()=='1') cout<<cnt-1<<'\n';
    else cout<<cnt<<'\n';
    return 0;
}

K

打表看看就知道了。

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

constexpr int N = int(1e6);
int s[N+1];

void solve()
{
    int n;
    cin>>n;
    // cerr<<s[n]<<" ";
    if(s[n]==0) cout<<"Pinkie Pie\n";
    else if(s[n]==1||s[n]==n) cout<<"Fluttershy\n";
    else if(s[n]==n+1) cout<<"Pinkie Pie\n";
}
/*
1 2 3 4 5 ,1


*/
int main()
{
    // ios::sync_with_stdio(false);
    // cin.tie(nullptr);
    // cout.tie(nullptr);
    for(int i=1;i<=N;i++){

        s[i]=i^s[i-1];
        // cerr<<i<<" "<<s[i]<< '\n';
    }
    int T;
    cin>>T;
    while(T--)
        solve();
    return 0;
}