疫情当下,刷题或许能成为一种不错的缓解无聊的方式
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的算法来构造一种特殊的矩阵来达到特殊的差值
于是我构造了这么一种特殊情况
右上角的0起到封路的作用,使得这个矩阵只剩下上下两条路径
即上方路径: 和下方路径:
我希望上方的路径为正确路径,而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;
}