【训练】Codeforces Round #877 (Div. 2) ABC题解

Codeforces Round #877 (Div. 2)

A Blackboard List

问题:一开始黑板上有两个数,后面每一次在黑板上选择两个数,增加他们的差的绝对值到黑板上,给出黑板上最后出现过的数字,求一开始的两个数之间的任何一个。
结论:板上任何负整数都必须是原来的两个数字之一,直接输出。如果没有负数就输出最大值。

因为任何两个数字之间的绝对差都是非负数,也就是后面产生的数一定是非负数,负数只有可能是一开始就存在。

因此,如果有任何负数,直接输出其中一个。

如果只有非负整数,请注意执行操作后最大数字保持不变,因为对于非负整数a和b,其中a≤b,我们有|a-b|=b-a≤b。因此,在这种情况下,列表中的最大数字必须是原来的一个数字。

复杂度:O(n)

代码

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

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        scanf("%d",&n);
        int ans=0;
        int maxzhi=INT_MIN;
        int shuru;
        for(int i=0;i<n;++i)
        {
            scanf("%d",&shuru);
            if(shuru<0)ans=shuru;
            else maxzhi=max(maxzhi,shuru);
        }
        if(ans==0)printf("%d\n",maxzhi);
        else printf("%d\n",ans);
    }
    return 0;
}

B Minimize Permutation Subarrays

结论:把最大值移动到1和2中间。
让Ax设为在p中的位置为x的索引,考虑如果An在A1和A2之间会发生什么。请注意,任何大小大于1的排列子数组都必须包含A1和A2。因此,它也必须包含所有介于其中的索引,包括An。因此,n是排列子数组的一个元素,因此其大小至少为n,并且必须是整个数组。

因此,如果An在A1和A2之间,唯一的排列子数组是[A1,A1]和[1,n]。这两个子数组始终是排列,因此这是最小的。

为了实现这一点,我们有三种情况:

如果An和A1和A2之间,则交换An和An。(其实就不用操作)

如果An < A1且A2 < An,则用A1或A2中的较小值替换An。

如果An > A1且A2 > An,则用A1或A2中的较大值替换An。

在这三个情况下,交换后An将位于A1和A2之间,从而最小化排列子数组的数量。

复杂度:O(n)

代码

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        scanf("%d",&n);
        int zhizhen1,zhizhen2,zhizhenn;
        for(int i=1;i<=n;++i)
        {
            int shuru;
            scanf("%d",&shuru);
            if(shuru==1)zhizhen1=i;
            else if(shuru==2)zhizhen2=i;
            else if(shuru==n)zhizhenn=i;
        }
            if(zhizhenn>max(zhizhen1,zhizhen2))cout<<zhizhenn<<" "<<max(zhizhen1,zhizhen2)<<endl;
            else if(zhizhenn<min(zhizhen1,zhizhen2)) cout<<zhizhenn<<" "<<min(zhizhen1,zhizhen2)<<endl;
            else cout<<zhizhenn<<" "<<zhizhenn<<endl;
    }
    return 0;
}

C No Prime Differences

问题:求一个n*m的矩阵,要求每一个数字相邻的数字纸差不能是质数。
结论:每一行按顺序排,第一列相差的值弄成非质数的就行,二维问题优化成一维的问题。
如果我们按照从左上角到右下角的顺序填写数字,例如对于n=5和m=7,相邻差值只有1和m。因此,如果m不是质数,则可以解决这个问题。现在我们重新排列行以使其在m是否为质数的情况下都能工作。将前⌊n/2⌋行放在第2、4、6…行,将最后⌈n/2⌉行放在第1、3、5…行。

由于我们只是从上面的解重新排列行,所有水平差值都是1,而垂直差值是大于等于4的m的倍数。因此,只要垂直差值不等于m本身,它们就必须是合数。
在这里插入图片描述

因为n≥4,在这个排序中没有一行与其原始相邻行相邻,因此所有垂直差值都大于m,因此也是合数。

因此,我们可以使用这个最终网格,无论m是否为质数。

复杂度:O(nm)

代码

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n,m;
        scanf("%d %d",&n,&m);
        for(int i=1;i<n;i+=2)
        {
            for(int j=1;j<=m;++j)
                if(j==1)printf("%d",i*m+j);
                else printf(" %d",i*m+j);
            printf("\n");
        }        
        for(int i=0;i<n;i+=2)
        {
            for(int j=1;j<=m;++j)
                if(j==1)printf("%d",i*m+j);
                else printf(" %d",i*m+j);
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

想要AC的dly

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

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

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

打赏作者

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

抵扣说明:

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

余额充值