Codeforces Round 884 (Div. 1 + Div. 2) A-D 题解

文章详细解析了CodeforcesRound884(Div.1+Div.2)比赛中的A至D题的解题思路和代码实现,包括后手必胜的石头游戏策略、构造最大MES值的排列、序列合并操作优化以及创建满足特定条件的字符串方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Codeforces Round 884 (Div. 1 + Div. 2) A-D 题解

cf链接

A:

题意:给你两个数a,b(a<b),两个人可以选择拿a个石头或者拿b个石头,现在让你给出石头的数量,让在这种情况下后手必胜(无法拿石头的一方输。)

提示:这里可以添加学习目标

思路:

因为已知a,b石头的大小关系,那么只要
a不为1,使石头数量为1,这样先手拿不了自然赢;
   ~~   如果a为1,
     ~~~~      那么看如果2*a<=b,即b大于2的话,直接使石头为2即可。
     ~~~~      否则b小于2,但是b又大于1,那么b只能为2,直接输出3.

代码:


void slove( )
{
   int t;
   int a,b;
   cin>>a>>b;
   if(a==1&&b==2)
   cout<<3;
   else if(a==1)
   cout<<2*a;
   else cout<<a-1;


   cout<<endl;
}

B:

题意:让你构造一个长度为n的排列,同时使这个排列内的MES值尽可能大,
MES代表 代表不出现在区间中的最小正整数。

思路:

ps:(当时写b题的时候脑袋太蠢了一直卡着导致心态崩了,现在感觉还是想太多/没想到点子上)。

因为要使MES达到最大,那么就要使质数尽可能出现的少,那么非质数就出现的最多,
那么对于第一个非质数1,就要尽可能出现的多在子序列中,那么1是肯定需要放在最中间的。
然后在1已经在中间的前提下,如果数组内不存在2或者3,那么MES一直是质数即是一个合法的答案
如果数组没包含1,那么MES为1,无论怎么放置都是一个无效的答案
如果数组里包含1,那么如果把2和3放在最前面和最后面,那么只要不是区间为[1,n]
那么将都是一个合法的答案。
所以只需要将1,2,3的位置放好,那么其他数完全可以随便放,这种情况就是最优的情况

代码:(用的cf官方代码自己的写的依托答辩)

    #include <bits/stdc++.h>
    using namespace std;
    
    int a[200000];
    int main() {
        int i;
        int t,n;
        scanf("%d",&t);
        while (t--) {
            scanf("%d",&n);
            if (n == 1) printf("1\n");
            else if (n == 2) printf("1 2\n");
            else {
                int c = 4;
                fill(a,a+n,0);
                a[0] = 2,a[n/2] = 1,a[n-1] = 3;
                for (i = 0; i < n; i++) {
                    if (a[i] == 0) a[i] = c++;
                }
                for (i = 0; i < n; i++) printf("%d%c",a[i],(i == n-1) ? '\n':' ');
            }
        }
        return 0;
    }

C:

题意:给定一个长度为n的序列,你可以进行任意次以下操作:
选择一个元素并删除它,之后使它两边的元素合并成一个元素,值为两者之和
问你最后的元素最大可能为多少。

思路:

自己模拟了之后可以发现,对于某一个元素进行操作时,剩下的所有元素的下标的奇偶性都不发生改变。那么这个有什么用呢,再仔细点我们可以发现,我们合并的两个元素,他们之间的下标的奇偶性是一致的。
那么得出结论,对于长度为n的序列,只有下标的奇偶性一致的元素才可以被合并在一起,那么直接比较只加偶数和只加奇数的情况的和,取最大值就可以了(下标的奇偶)。
因为要取最大值,那么对于负数可以直接删除。
同时如果全为负数,需要留一个最大的负数作为答案。

代码:

void slove( )
{
   int t;
   cin>>n;

   vector<ll>q;
   bool st=0;
   for(int i =1;i<=n;i++){
   	cin>>s[i];
   	if(s[i]>0)st=1;
   }

   if(st==0){//全是负数
   	ll res=-1e18;
   	for(int i =1;i<=n;i++)
   	res=max(res,s[i]);
   	cout<<res<<endl;
   	return ;
   } 

   ll res1=0,res2=0;
   for(int i =0;i<q.size();i+=2) 	if(q[i]>0)	res1+=q[i];
   for(int j =1;j<q.size();j+=2)    if(q[j]>0)  res2+=q[j];
   cout<<max(res1,res2);
   
   cout<<endl;
}

D:

题意:给你一个字符串的长度n,把这个字符串连续的分成a行b列的二维字符串(a*b==n),并且要求每个字符的相邻字符都不相同。让你输出这个字符串,并且这个字符串的字符种类最少。

思路:

这里借了个图对于相邻字符不 同的解释:
在这里插入图片描述
对于一个长度为m的字符串s,如果是字符串总长度为n的因子,
没有一个可以整除m,那么这个字符串就是一个合法的。
那么可以先求出来一个最短的字符串k,然后以这个字符串为模板不断增加就好。

(比如n是8,因子为1 2 4 8,最小m的长度为3,那么可以为abc,然后以此为循环节增加,如果会产生相邻字符相同的情况下,那么即k[i]=k[i+3*x],x为1,2…), 但是n中不存在3的因子,那么abc就是合法且最短的一个循环节)。

代码:

void slove( )
{
   int t;
   sc_int(n);

   int sum=n;
   s[0]='a';	
   for(int i =1;i<=n;i++)
   {
   	s[i]=s[i-1]+1;
   	if(n%i!=0){
   		sum=i;
   		break;
   	}
   }

   	for(int j =0,i=1;i<=n;i++,j=(j+1)%sum)
   	{
   		cout<<s[j];
   	}
   
   cout<<endl;
}

ps:继续打吧,毕竟还能顺便陪陪对象(bus)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值