比赛链接:https://codeforces.com/contest/1384
A.Common Prefixes
题意:
给你n个数表示数组a,让你输出n+1个字符串,使第i+1个字符串和第i个字符串有a[i]位前缀相同。
AC
#include<bits/stdc++.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const LL N = 1e5 + 10;
int a[105];
char s[105];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=60;i++)
{
s[i-1]='a';
printf("a");
}
printf("\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=a[i];j++)
{
printf("%c",s[j-1]);
}
for(int j=a[i]+1;j<=60;j++)
{
printf("%c",(s[j-1]+1)%26+'a');
s[j-1]=(s[j-1]+1)%26+'a';
}
printf("\n");
}
}
return 0;
}
B2. Koa and the Beach (Hard Version)
小吐槽:这道题放在B的位置上是真的恶心(是B题该有的水准吗?),比赛最后时间过了B1,B1改B2多打了个break,赛后一发过
题意:
一个人在s的位置上,要到t的位置,在s和t之间,有n米路,第i米位置有a[i]的水深,给你了l,表示这个人不能在水深超过l的水里,不然会被淹死,然后又给你了k,表示潮汐,p[[数组表示潮汐,长度为2k,p[0,1,2,3,…k-1,k,k-1,k-2,…1];
假设当时时间为t,那么第i位置的水深就为d[i]=a[i]+p[t%2k];要保证人走到第i的位置的时候,d[i]<=l;
问你,这个人能不能走到t。
思路
我当时是这样想的,我们可以贪心一下,我们最开始走到一个位置,那么我们这个位置的保持潮汐下落的最大值,因为潮汐是有规律的,一凹一凸。手绘了一张假图,帮助理解
就这样往后判断就行。
复杂度也不是很高
/*
* @沉着,冷静!: 噗,这你都信!
* @LastEditors: HANGNAG
* @LastEditTime: 2020-07-25 10:02:07
* @FilePath: \undefinedc:\Users\13099\Desktop\niuke\main.cpp
*/
#include <bits/stdc++.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const LL N = 1e5 + 10;
int a[300005];
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int n, k, l;
scanf("%d%d%d", &n, &k, &l);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
int flog = 0, ku;
int num = -k;
for (int i = 1; i <= n; i++)
{
int u = l - a[i];
ku = 0;
if (u < 0)
{
flog = 1;
break;
}
if (num < 0)
{
if (abs(num) > u)
{
num = -u;
ku = 1;
}
else
{
num++;
ku = 1;
}
}
else
{
if (num + 1 <= u)
{
num++;
ku = 1;
}
}
// for(int j=1;j<=k;j++)
// {
// if(abs(num+j)<=u)
// {
// num=num+j;
//
// }
// }
if (num >= k || u >= k)
{
num = -k;
}
//printf("%d*",num);
if (ku == 0)
{
flog = 1;
break;
}
}
if (flog)
{
printf("No\n");
}
else
{
printf("Yes\n");
}
}
return 0;
}
C. String Transformation 1
题意
题意很简单,就是给你两个字符串a,b,然后你可以选择a里面相同的字符,然后把他们变大,问最少几次这样操作可以使a字符串转变为b字符串。如果不可能输出-1.
思路
因为题目中告诉你,最多20个,而且只能增加,那么我们就每次枚举当前要改变的字符,把他们加到这些选中的数的对应b字符串中的最小值,以此类推,操作一次ans+1,最后输出ans,如果出现相同位置上,最开始,b[i]<a[i],因为只能增加,所以不可能,就输出-1。
AC
#include<bits/stdc++.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const LL N = 1e5 + 10;
int a[N];
int b[N];
char s1[N],s2[N];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
scanf("%s %s",s1,s2);
int flog=0;
int ans=0;
for(int i=1;i<=n;i++)
{
a[i]=s1[i-1]-'a'+1;
b[i]=s2[i-1]-'a'+1;
if(b[i]<a[i])
{
flog=1;
break;
}
}
if(flog)
{
printf("-1\n");
}
else
{
int minn=1000;
int ff=0;
for(int i=1;i<=20;i++)
{
minn=1000;
ff=0;
for(int j=1;j<=n;j++)
{
if(a[j]==i&&b[j]>a[j])
{
ff=1;
minn=min(minn,b[j]-a[j]);
}
}
for(int j=1;j<=n;j++)
{
if(a[j]==i)
{
a[j]+=minn;
}
}
ans+=ff;
}
printf("%d\n",ans);
}
}
return 0;
}
D. GameGame
题意:
两个人玩游戏,给你一些数,每个人的初始分数都是0,然后两个人可以依次选择一些数,假设当前K的分数为x,然后K选择了y,然后现在的分数就是x^y(x异或y),现在是K先走,问你K最后的情况,是WIN(赢),LOSE(输),DRAW(平局)
思路
异或我们都知道,相同为1,不能为0,那么我们现在只需要找到最高一位,数目为奇数的位置,(因为10000>01111,只要最高位掌握在手,还怕后面的?),找数目为奇数的主要是因为两个人拿,分脏不均,总会有一个有,一个没有。究竟是谁有,谁没有,还是要看这奇数的数量和不含这一位二进制数的个数。
1,每一位二进制数的书面都是偶数,平局
2.K赢的条件:
假设现在第i位的二进制数目不同,数目为num[i];
K拿了(num[i]/2+1)个,num[i]/2+1是个奇数,那么就是说我们K拿了这些之后,无论你怎么拿,我都有最高位这些在手。
还有一种就是K拿了(num[i]/2+1)个,但是这个数是个偶数,但是现在假设还有u个没有这一二进制位的数,就相当于废数,如果k%2==1,我们开头拿一个废数充数,然后情况就完全反转了,我们就可以放心的拿了,他要是也拿废数,我们就再拿一个废数,因为只要k%2=1,一定可以保持我们拿的废数多,让他变成先手,必输手。
(语言如果描述不清楚的地方,可以自己推推,也可以留言解决。)
AC
/*
* @沉着,冷静!: 噗,这你都信!
* @LastEditors: HANGNAG
* @LastEditTime: 2020-07-25 20:49:19
* @FilePath: \undefinedc:\Users\13099\Desktop\workspace\worksapce\main.cpp
*/
#include <algorithm>
#include <string.h>
#include <iostream>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;
int num[50];
int bit(int x)
{
int tot=0;
while(x)
{
if(x&1)
{
num[tot]++;
}
x/=2;
tot++;
}
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
memset(num,0,sizeof(num));
int n;
scanf("%d", &n);
int x;
for (int i = 1; i <= n; i++)
{
scanf("%d", &x);
bit(x);
}
int flog=0;
for(int i=32;i>=0;i--)
{
if(num[i]%2)
{
if(((num[i]+1)/2%2==0&&(n-num[i])%2==1)||(num[i]+1)/2%2==1)
{
printf("WIN\n");
}
else
{
printf("LOSE\n");
}
flog=1;
break;
}
}
if(!flog){
printf("DRAW\n");
}
}
return 0;
}