A 我爱编程,编程使我快乐。

签到,直接输出就行

#include <stdio.h>
 
int main()
{
    printf("我爱编程,编程使我快乐。");
}

B 二进制翻转

根据题意只需要计算数组中连续的0的段数即是答案,注意到每个连续的0的段前面必定有一个1(如果起始为0单独计算),所以记录前1后0的位置的数量即是连续的0的段的数量。

#include <stdio.h>
int n;
int a[200005];
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    int ans = 0;
    if (a[0] == 0) ans++;
    for (int i = 1; i < n; i++) {
        if (a[i] == 0 && a[i - 1] == 1) ans++;
    }
    printf("%d\n", ans);
    return 0;
}

#include <bits/stdc++.h>

using namespace std;
int n;
int a[200005];
int main() {
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    int ans = 0;
    if (a[0] == 0) ans++;
    for (int i = 1; i < n; i++) {
        if (a[i] == 0 && a[i - 1] == 1) ans++;
    }
    cout << ans << endl;
    return 0;
}

C 二进制扩列

由题意知原先的字符串经过扩展后必定是一边一个0另一边一个1,所以使用两个变量标记左右边界,如果符和一边是0另一边是1则符和条件,可以继续收缩。由于你要得到最短的最初的字符串,所以你只要找到不符合的位置,然后输出此时字符串的长度即可。

#include <stdio.h>
char s[100005];
int main() {
    int n;
    scanf("%d%s", &n, s);
    int l = 0, r = n - 1, ans = 0;
    while (s[l] != s[r] && l < r) {
        l++, r--, ans++;
    }
    printf("%d\n", n - ans * 2);
    return 0;
}
#include <bits/stdc++.h>
 
using namespace std;
 
int main()
{
    int n;
    string s;
    cin >> n >> s;
    int l = 0, r = n - 1, ans = 0;
    while (s[l] != s[r] && l < r) {l ++, r --, ans ++;}
    cout << n - ans * 2 << endl;
    return 0;
}

D 睡过去的jxh仍在学习

对数组a进行排序,然后把前m个小的数相加即可,注意题目的数据范围,不能用n^2的排序方法,可以用快排、归并之类的,使用c++的话,可以直接用sort函数。如果不会这些的话,注意到数组a中的元素都是1e5以内的正整数,可以开一个数组b来记录数组a中元素出现的个数,即b[x]代表x在a中出现的次数,x为0时,没有出现过。这样就可以从1开始遍历b,找到a中前m个小的数,把它们相加即可。

#include <stdio.h>
  
int a[100005];
int main() {
    int n, m, cnt = 0;
   	scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++) {
        int x;
       	scanf("%d", &x);
        a[x]++;
    }
    long long ans = 0;
    for (int i = 1; i <= 100000; i++) {
        long long x = a[i];
        if (x > m - cnt)	x = m - cnt;
        cnt += x;
        ans += i * x;
        if (cnt == m) break;
    }
    printf("%lld", ans);
    return 0;
}



E 寝室的宝箱(简单版)

简单的加减计算,对于输入的数字和字符调用相关的式子即可

#include<stdio.h>
int main()
{
    int x,y;
    char ch;
    scanf("%d %c %d",&x,&ch,&y);
    printf("%d",(ch=='+'?x+y:x-y));
    return 0;
}

F 寝室的宝箱(困难版)

如果选择整形进行计算需要考虑使用longlong,对于除法需要特判一下,另外使用浮点数进行计算由于没有卡精度所以也是可以过的。

#include<stdio.h>

int main()
{
    long long x,y;
    char ch;
    scanf("%lld %c %lld",&x,&ch,&y);
    if(ch=='/') 
    {
        if(x%y)printf("%.2lf",(double)x/y);
        else printf("%lld",x/y);
    }
    else printf("%lld",ch=='+'?x+y:(ch=='-'?x-y:x*y));
    
    return 0;
}

G 排队

单向链表的简单模拟,反向记录一下每个人后面的人即可,可以标记一下前面有人的人的编号没有标记的就是队首,另外有n可能为1赛时很多人wa这个点了。

#include<stdio.h>
int a[5005],st[5005];
int main()
{
    int n,h;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        a[y]=x;
        st[x]=1;
    }
    for(int i=1;i<=n;i++)
        if(!st[i])
        {
            h=i;
            break;
        }
    while(h)
    {
        printf("%d ",h);
        h=a[h];
    }
    return 0;
}

H jxh和lhy的决斗

大模拟,模拟过程见注释


#include <stdio.h>

struct player
{
	int hp, mp, atk, x, y, z;
	int hpx, def, deft;//分别是血量最大值、目前护盾值、护盾持续时间 
}jxh, lhy;

//攻击函数 
struct player atk(struct player a, struct player b)
{
	int x = a.atk;
	//先判断护盾值是不是能够抵挡此次攻击,如果可以,只扣除护盾 
    if (b.def >= x)    b.def -= x;
    //护盾值小于伤害的话,血量扣除使用护盾抵扣后的伤害并将护盾值置为0 
    else 
	{
        x -= b.def;
        b.def = 0;
        b.hp -= x;
    }
    return b;
}

//回血函数 
struct player rec(struct player a)
{
	a.hp = a.hp + a.x;
	//需要注意回血不能超过血量上限 
	if (a.hp > a.hpx)	a.hp = a.hpx;
	return a;
}

//防御函数 
struct player def(struct player a)
{
	//重置护盾值和护盾持续时间 
	a.def = a.y;
    a.deft = 3;
	return a;
}

//释放技能函数 
struct player mfa(struct player a, struct player b)
{
	//判断mp是否足够释放技能,可以的话使用攻击函数攻击三次 
	if (a.mp >= a.z)
	{
        b = atk(a, b);
        b = atk(a, b);
        b = atk(a, b);
    }
	return b;
}

h
模拟就行,具体看代码里的注释
int main()
{
	int t;
	scanf("%d", &t);
	while (t -- )
	{
		scanf("%d%d%d%d%d%d", &jxh.hp, &jxh.mp, &jxh.atk, &jxh.x, &jxh.y, &jxh.z);
		scanf("%d%d%d%d%d%d", &lhy.hp, &lhy.mp, &lhy.atk, &lhy.x, &lhy.y, &lhy.z);
		//记录血量上限 
		jxh.hpx = jxh.hp;
		lhy.hpx = lhy.hp;
		//重置护盾值和护盾持续时间 
		jxh.def = jxh.deft = lhy.def = lhy.deft = 0;
		int n, flag = 0, ans = 0;
		//判断谁先手,并记录是否交换 
		if (jxh.atk < lhy.atk)
		{
			struct player temp = jxh;
			jxh = lhy;
			lhy = temp;
			flag = 1;
		}
		scanf("%d", &n);
		//经过判断后变量jxh先手,变量lhy后手 
		while (n -- )
		{
			int a, b;
			scanf("%d%d", &a, &b);
			//如果已经出现结果,跳过 
			if (ans)	continue;
			//护盾持续时间减1,如果持续时间为0,护盾值归零 
			jxh.deft = jxh.deft - 1;
			if (jxh.deft < 0)	jxh.deft = 0;
			if (!jxh.deft)	jxh.def = 0;
			//判断操作 
			switch (a)
			{
				case 1:
					lhy = atk(jxh, lhy);
					break;
				case 2:
					jxh = rec(jxh);
					break;
				case 3:
					jxh = def(jxh);
					break;
				case 4:
					lhy = mfa(jxh, lhy);
					//注意释放技能后要扣除mp 
					if (jxh.mp >= jxh.z)	jxh.mp -= jxh.z;
					break;
			}
			//判断是否出现结果 
			if (lhy.hp <= 0)
			{
				ans = 1;
				continue;
			}
			lhy.deft = lhy.deft - 1;
			if (lhy.deft < 0)	lhy.deft = 0;
			if (!lhy.deft)	lhy.def = 0;
			switch (b)
			{
				case 1:
					jxh = atk(lhy, jxh);
					break;
				case 2:
					lhy = rec(lhy);
					break;
				case 3:
					lhy = def(lhy);
					break;
				case 4:
					jxh = mfa(lhy, jxh);
					if (lhy.mp >= lhy.z)	lhy.mp -= lhy.z;
					break;
			}
			if (jxh.hp <= 0)	ans = -1;
		}
		//平局 
		if (!ans)	printf("-_-\n");
		else
		{
			//若ans为1,先手赢,否则后手赢 
			//flag为1时lhy为先手,否则jxh为先手 
			if (flag)	 printf("%s\n", ans == 1 ? "lhy!lhy!lhy!!!" : "不愧是你啊,jxh!");
			else	 printf("%s\n", ans == -1 ? "lhy!lhy!lhy!!!" : "不愧是你啊,jxh!");
		}
	}
}