Codeforces Round #630 (Div. 2)

疫情当下,刷题或许能成为一种不错的缓解无聊的方式

A. Exercising Walk

题意:

矩形区域内,给定一定数量上下左右四种行走操作数量,问是否能在规定区域能完成而不超界。

思路:

上下,左右每对对立的操作只需要考虑之间的差,然后判断是否超界即可。因为,每对操作可以相互抵消。

最后考虑一种特殊情况,就是对立操作刚好数量相同,检测一下两边是否有至少一个空间来执行操作即可。

代码:

/*
Author Owen_Q
*/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 1e7+5;

int a[maxn];

int main()
{
    int n;
    //freopen(".txt","r",stdin);
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    scanf("%d",&n);
    while(n--)
    {
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        int x,y,x1,y1,x2,y2;
        scanf("%d%d%d%d%d%d",&x,&y,&x1,&y1,&x2,&y2);
        int xf,yf;
        bool ok = true;
        xf = x - a + b;
        if(xf<x1||xf>x2)
            ok = false;
        else if(a>0&&b>0&&x==x1&&x==x2)
            ok = false;
        yf = y - c + d;
        if(yf<y1||yf>y2)
            ok = false;
        else if(c>0&&d>0&&y==y1&&y==y2)
            ok = false;
        if(ok)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

B. Composite Coloring

题意:

n个1k以内的数,给每个数上色,要求相同颜色的数不能互质,问能否用m(不超过11)种颜色完成

思路:

不难发现,32以内的质数刚好有11个,因此,这11个数必定可以组成1k以内所有数,因此,以这11个质数作为因数来上色,即可

代码:

/*
Author Owen_Q
*/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 1e7+5;

int a[maxn],c[maxn];

int main()
{
    int t;
    //freopen(".txt","r",stdin);
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    int p[11] = {2,3,5,7,11,13,17,19,23,29,31};
    scanf("%d",&t);
    while(t--)
    {
        //printf("t=%d\n",t);
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            c[i] = -1;
        }
        int col = 1;
        for(int now=0;now<11;now++)
        {
            bool ne = false;
            for(int i=0;i<n;i++)
            {
                if(c[i]==-1&&a[i]%p[now]==0)
                {
                    ne=true;
                    c[i] = col;
                }
            }
            if(ne)
                col++;
        }
        printf("%d\n%d",col-1,c[0]);
        for(int i=1;i<n;i++)
            printf(" %d",c[i]);
        printf("\n");
    }
    return 0;
}

C. K-Complete Word

题意:

定义k-完全串的概念:

1.长度为k倍数

2.回文串

3.周期为k的循环串

问最少的操作步数变普通串k为k-完全串

思路:

看似条件很多很苛刻,但如果自己琢磨这些复杂条件之间的关系,却发现,这些条件刚好构造了一种特殊情况

那就是刚好确保每个周期内都是相同的回文串。

这样的话,就强行定下了串中特定位置必须为相同的数,按照这些位置将串中需要相同字母的位置分组,组内判断最少需要变动的字母数即可

代码:

/*
Author Owen_Q
*/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 1e7+5;

char a[maxn];

int b[26];

int main()
{
    int t;
    //freopen(".txt","r",stdin);
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    scanf("%d",&t);
    while(t--)
    {
        int n,k;
        scanf("%d%d",&n,&k);
        int d = n/k;
        scanf("%s",a);
        int num = 0;
        for(int pos=0;pos<k/2;pos++)
        {
            for(int i=0;i<26;i++)
                b[i] = 0;
            for(int i=0;i<d;i++)
            {
                b[a[i*k+pos]-'a']++;
                b[a[i*k+k-1-pos]-'a']++;
            }
            int maxb = 0;
            for(int i=0;i<26;i++)
                maxb = max(maxb,b[i]);
            num += 2*d - maxb;
        }
        if(k%2==1)
        {
            int pos = k/2;
            for(int i=0;i<26;i++)
                b[i] = 0;
            for(int i=0;i<d;i++)
            {
                b[a[i*k+pos]-'a']++;
            }
            int maxb = 0;
            for(int i=0;i<26;i++)
                maxb = max(maxb,b[i]);
            num += d - maxb;
        }
        printf("%d\n",num);
    }
    return 0;
}

D. Walk on Matrix

题意:

Bob玩一个游戏,要求从矩阵左上角单向走到右下角,每次行走都将走前后格子内的数异或,要求寻找一种路径使得最终异或值最小。

然而这题并不是要求你找这个异或最小值,也不是要你找路径,而是“聪明的Bob”设计了一种动态规划算法来求这个最小值,然而他的算法错了,现在希望你帮他去纠正。

还没完,你帮他纠正完之后,显然会发现,Bob的算法会比正确的值大,这题最终的意图是,给定你一个数k,要求你构造一个矩阵使得Bob的算法在你构造的矩阵上跑出来的结果会比正确值刚好大k。

思路:

经过Bob一系列操作,这题显然变成了一个构造题,针对bob的算法来构造一种特殊的矩阵来达到特殊的差值

于是我构造了这么一种特殊情况

\begin{bmatrix} B & A & 0\\ C & B & A \end{bmatrix}

右上角的0起到封路的作用,使得这个矩阵只剩下上下两条路径

即上方路径:B \rightarrow A\rightarrow B\rightarrow A 和下方路径:B\rightarrow C\rightarrow B\rightarrow A

我希望上方的路径为正确路径,而Bob的算法刚好会跑下方的路径。

首先构造B为辅助,希望B并不改变最终的值,即B或A为A,B或C为C。这样,当走到中间B点处时,上方走来的值刚好为A,下方走来的值刚好为C。

第二步,就是到达终点,构造A或C为0,这样的话Bob走到终点获得的值刚好为0,而正确算法的值刚好为A,而差值恰好就是A。

那么,开始构造:

根据分析,A当然就是k

而为了诱导Bob进入下方区域,只需要保证C的值比B大即可。而为了使得A与C相或为0,可以直接构造C为二进制比A最高位高1,且除最高位为1以外所有位去全为0的数。

最后B只需将A和C求与即可

代码:

/*
Author Owen_Q
*/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 1e7+5;

int a[maxn];

int main()
{
    int k;
    //freopen(".txt","r",stdin);
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    scanf("%d",&k);
    int a=0,b=1,c=1;
    if(k>0)
    {
        int d=0;
        while((k>>d)>1)
            d++;
        /*a = 1<<d;
        c = k ^ a ^ (1<<(d+1));*/
        a = k;
        c = 1<<(d+1);
        b = a | c;
    }
    printf("2 3\n");
    printf("%d %d %d\n%d %d %d\n",b,a,0,c,b,a);
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值