CodeChef 补题

CodeChef 做题记录

The XOR-OR Dilemma

Chef has an array AA of length NN such that Ai=iAi=i.

In one operation, Chef can pick any two elements of the array, delete them from AA, and append either their bitwise XOR or their bitwise OR to AA.

Note that after each operation, the length of the array decreases by 11.

Let FF be the final number obtained after N−1N−1 operations are made. You are given an integer XX, determine if you can get F=XF=X via some sequence of operations.

In case it is possible to get F=XF=X, print the operations too (see the section Output format for more details), otherwise print −1−1.

给定1~n,你可以进行两种操作:

  • 1 x y if you want replace x and y with x OR y.
  • 2 x y if you want replace x and y with x XOR y

然后将x,y移除并将新值插入。给定x,求使得最终剩下的值为x的方案

构造的思路就是把所有的数全部或起来,然后和最终的数做异或得到tmp。然后用二进制拼接出tmp,用或操作,然后把剩下的没用到的数或起来最终两数异或便是答案。期间,特判不存在的解。

const int N=200010,M=N*2,mod=1e9+7;
int n,m,k,a[N];
struct Op{
    
    
    int op,a,b;
};

void solve(){
    
    
	n=read(),m=read();
    int all=0;rep(i,1,n) all|=i;
    if(all<m){
    
    
        print(-1);
        return ;
    }
    int tmp=(all^m);
    if(tmp==0){
    
    
        int last=1;
        for(int i=2;i<=n;++i){
    
    
            printf("1 %d %d\n",i,last);
            last|=i;
        }
        return ;
    }
    vector<Op> vec(0);
    vector<int> temp;
    map<int,int> mp;
    for(int i=0;(1<<i)<=tmp;++i)
        if(tmp>>i&1){
    
    
            mp[1ll<<i]=1;
            temp.push_back(1ll<<i);
        }
    int cnt=0,last=0;
    for(int i=1;i<=n;++i){
    
    
        if(mp.count(i)) continue;
        if(cnt==0) {
    
    
            cnt++;
            last=i;
        }
        else {
    
    
            vec.push_back({
    
    1,last,i});
            last|=i;
        }
    }
    if(last!=all){
    
    
        print(-1);
        return ;
    }
    int u=0;
    for(int i=0;i<temp.size();++i){
    
    
        if(i==0) u=temp[i];
        else vec.push_back({
    
    1,u,temp[i]}),u|=temp[i];
    }
    vec.push_back({
    
    2,last, u});
    for(auto u:vec){
    
    
        printf("%d %d %d\n",u.op,u.a,u.b);
    }
}

Codecherf START51 Div4 Chef & Cook Game

H

There is a non-negative integer array AA of length NN. Chef and Cook will play a game on the array with Chef starting first.

In one turn the player will perform the following operation:

  • Choose two indices i,j such that 1 ≤ i < j ≤ N 1 \le i \lt j \le N 1i<jN and A i > 0 A_i \gt 0 Ai>0.
  • Set A i ← A i − 1 A_i \gets A_i-1 AiAi1 and A j ← A j + 1 A_j \gets A_j+1 AjAj+1,subtract 1 from A i A_i Ai and add 1 to A j A_j Aj

The player who is unable to perform the operation loses. If both Chef and Cook play optimally, who will win?

解法

首先,对于a[i]是偶数的位置,我们很容易想出来对照操作:只要你选了这个位置,我也选,因此对于偶数的位置我们不需要考虑。因此单独考虑a[i]为奇数的位置,我们可以将其转化为Nim游戏,对于i位置,可以移动到大于i的任意位置,因此可以看作可以取1~N-i个石子,所以我们把奇数位置的所有N-i异或起来,如果异或和不为0,则为先手必胜,否则先手必败。

void solve(){
    
    
	cin>>n;
	rep(i,1,n) cin>>a[i];
	if(n==1){
    
    
		cout << "Cook\n";
		return ;
	}
	LL sum=0;
	rep(i,1,n){
    
    
		if(a[i]&1) sum^=(n-i);
	}
	cout << (sum?"Chef":"Cook") << "\n";
}

September Lunchtime 2022 (Rated for All) (Based on EJOI)

Remove Numbers

Two players are playing a game. They are given an array A_1, A_2, \ldots, A_NA1,A2,…,A**N as well as an array B_1, B_2, \ldots, B_MB1,B2,…,B**M.

The game consists of MM rounds. Players are participating in rounds alternatively. During the ii-th round (for ii from 11 to MM) the corresponding player (first player, if ii is odd, and second if ii is even) has to do exactly one of the following:

  • remove all elements from the array AA that are divisible by B_iB**i,
  • remove all elements from the array AA that are not divisible by B_iB**i.

The first player wants to minimize the sum of the remaining elements in the array AA after all MM rounds, and the second wants to maximize it. Find the sum of the remaining elements in the array AA after all MM rounds if both players are playing optimally.

题解:

首先观察到尽管 A i A_i Ai的范围非常的大,但是如果在m比较大的情况下,最终答案直接是0.那么m在什么范围下答案直接是0呢?

假设对于想要让数组尽可能小的那个人操作,对于他操作的集合首先尽量满足每个数都不一样,然后由于 A i ≤ 1 0 14 A_i \le 10^{14} Ai1014而且 18 ! > 1 0 14 18! \gt 10^{14} 18!>1014所以对于这个人当他操作18次或者以上的时候一定能把数组变成全部都是0.因此对于两个人而言,如果数组容量大于36,则答案一定是0.对于数组容量小于36的情况直接搜索即可。

Code:https://www.codechef.com/viewsolution/75158402

Adjacent Pairs

看别人代码写的,有点神奇的剪枝…
Code:https://www.codechef.com/viewsolution/75309277

Alternative Sufferings

在这里插入图片描述

这道题蛮有意思是的。首先我们得先做一遍整个字符串的操作。然后对于每个位置找到他第一次变成1的时间,然后变成1之后它后面的变化规律就是10101010…直接可以通过奇偶性来判断了。
Code:https://www.codechef.com/viewsolution/76198290

K - Beautiful Permutation

一道比较典的DP题,看数据范围可以设出状态dp[i][j][k][0/1]表示前i个位置分成j段其中选择了k个奇数,上一个选择的是奇/偶的方案数。
我们需要预先处理一下even[i]和odd[i]表示已经确定的位置的偶数和奇数的前缀和,便于转移。然后转移过程见代码。

Code:https://www.codechef.com/submit/KBPER?tab=statement

猜你喜欢

转载自blog.csdn.net/m0_51780913/article/details/127033414