ICPC 2024 武汉 VP

I. Cyclic Apple Strings

找 10 的个数即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <bits/stdc++.h>
using namespace std;

int main(){
    string s;
    cin>>s;
    int cnt=0;
    for(int i=0;i+1<s.size();i++){
        if(s[i]=='1'&&s[i+1]=='0')cnt++;
    }
    cout<<cnt<<endl;
}

K. Party Games

观察连续异或和,发现每次如果 %4 == 1 或 0 可以移走最左或最右的一个元素,反之则无法操作,或有两个元素能取,此时先手必败。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <bits/stdc++.h>
using namespace std;
#define ls now<<1
#define rs now<<1|1
#define endl "\n"
#define lowbit(x) ((x)&(-x))
typedef long long ll;
const int N=1e5+7, mod=1e9+7;

int n;

void solve(){
    cin>>n;
    bool flag=0;
    if(n<=3){
        if(n==1)flag=1;
    }
    else{
        int t=n%4;
        if(t<=1)flag=1;
    }
    if(flag)cout<<"Fluttershy\n";
    else cout<<"Pinkie Pie\n";
}

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

B. Countless Me

可以将所有元素加合起来后,分配到 n 个位置上

问题转化为如何分配,注意到要求的是按位或最小,明确如果某位按位或后为 1,这一位上的 1 就应该尽量多,同时,应该优先填满低位。

所以从高位往低位贪心,一次计算当前位数如果不填,sum 能否分配完,如果不能,就在当前位放尽可能多的 1。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <bits/stdc++.h>
using namespace std;
#define ls now<<1
#define rs now<<1|1
#define endl "\n"
#define lowbit(x) ((x)&(-x))
typedef long long ll;
const int N=1e5+7, mod=1e9+7;

int n;
int a[N],b[32];

void solve(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    ll sum=accumulate(a+1,a+1+n,0ll);
    for(int i=31;i>=0;i--){
        if(1ll*n*((1<<i)-1)>=sum)continue;
        int x=min(n*1ll,sum/(1<<i));
        b[i]=1;
        // cout<<i<<" ";
        sum-=x*(1<<i);
    }
    ll ans=0;
    for(int i=0;i<=31;i++){
        if(b[i])ans+=(1<<i);
    }
    cout<<ans<<endl;
}

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

F. Custom-Made Clothes

二分答案,寻找矩阵中有多少个值小于等于其。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <bits/stdc++.h>
using namespace std;
#define ls now<<1
#define rs now<<1|1
// #define endl "\n"
#define lowbit(x) ((x)&(-x))
typedef long long ll;
const int N=1e5+7, mod=1e9+7;

int n,k;

bool check(int mid){
    int x=n,y=1,cnt=n;
    while(x>0&&y<=n){
        printf("? %d %d %d\n",x,y,mid);
        cout<<endl;
        bool f;
        cin>>f;
        if(f)y++,cnt+=x;
        else x--,cnt--;
    }
    return cnt<=k;
}

void solve(){
    cin>>n>>k;
    int l=1,r=n*n,ans=0;
    while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid))l=mid+1,ans=mid;
        else r=mid-1;
    }
    cout<<ans<<endl;
}

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

D. ICPC

观察时限,$O(n^2)$ 解决问题。

显然从某一位开始,只会有两种走法,一种不变向走到头,另一种变向一次,这两种就足够覆盖所有情况,即足够覆盖所有位置。

所以,先通过前缀和,求得不变向时,从某一位置开始,走 t 秒的最大值。

接着通过不变向的最大值来求有变向时的。

$f[s][t] = max(g[s][t],g[s-1][t-1],g[s-2][t-2],…,g[s+1][t-1],g[s+2][t-2],…)$

正着先求 $f[s][t]=max(f[s-1][t-1],g[s][t])$,再倒着求 $f[s][t]=max(f[s+1][t-1],g[s][t])$ 即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <bits/stdc++.h>
using namespace std;
#define ls now<<1
#define rs now<<1|1
#define endl "\n"
#define lowbit(x) ((x)&(-x))
typedef long long ll;
const int N=5e3+7, mod=1e9+7;

int n;
ll a[N],s[N],g[N][2*N],f[N][2*N];

void solve(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        s[i]=s[i-1]+a[i];
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n+n;j++){
            int l=max(1,i-j);
            int r=min(n,i+j);
            g[i][j]=max(s[i]-s[l-1],s[r]-s[i-1]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n+n;j++){
            f[i][j]=max({f[i][j],f[i-1][j-1],g[i][j]});
        }
    }
    for(int i=n;i>=1;i--){
        for(int j=1;j<=n+n;j++){
            f[i][j]=max({f[i][j],f[i+1][j-1],g[i][j]});
        }
    }
    ll ans=0;
    for(int i=1;i<=n;i++){
        ll tmp=0;
        for(int j=1;j<=n+n;j++){
            tmp^=(j*f[i][j]);
        }
        ans^=(i+tmp);
    }
    cout<<ans<<endl;
}

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

M. Merge

观察到,相差为 1 的两个数相加后,只能为奇数,那么要操作,就必须找到偶数,所以我们只对偶数位查询,记当前偶数为 x,我们查询 x+1, x-1 是否存在,查询过程递归,如果当前查询值存在返回 1,否则查询当前值拆分后的两个数是否存在。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <bits/stdc++.h>
using namespace std;
#define ls now<<1
#define rs now<<1|1
#define endl "\n"
#define lowbit(x) ((x)&(-x))
#define int long long
typedef long long ll;
const int N=2e5+7, mod=1e9+7;

ll n,a[N];
map<ll,int>vis,tmp;

bool dfs(ll x){
    if(vis[x]>0){
        vis[x]--;
        tmp[x]++;
        return 1;
    }
    if((x%2)==0||(x==1))return 0;
    return dfs(x/2)&&dfs(x/2+1);
}

void solve(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        vis[a[i]]++;
    }
    sort(a+1,a+1+n,greater<ll>());
    for(int i=1;i<=n;i++){
        int t=a[i];
        if(vis[t]<=0)continue;
        vis[t]--;
        tmp.clear();
        if(dfs(t+1)){
            vis[t+t+1]++;
            continue;
        }
        for(auto [x,y]:tmp)vis[x]+=y;
        tmp.clear();
        if(dfs(t-1)){
            vis[t+t-1]++;
            continue;
        }
        for(auto [x,y]:tmp)vis[x]+=y;
        tmp.clear();
        vis[t]++;
    }
    vector<ll>ans;
    for(auto [x,y]:vis){
        if(x<1)continue;
        while(y>0){
            y--;
            ans.push_back(x);
        }
    }
    cout<<ans.size()<<endl;
    for(auto x:ans)cout<<x<<" ";
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int t=1;
    // cin>>t;
    while(t--)solve();
    return 0;
}
Licensed under CC BY-NC-SA 4.0
最后更新于 Sep 11, 2025 16:27 +0800
发表了95篇文章 · 总计15万2千字
永远相信美好的事情即将发生。
使用 Hugo 构建
主题 StackJimmy 设计