第一次 ACM—TC 联合周赛题解

个人博客链接

题目分析

  • 题目分布:计科-ACM工作室 B E F G H I 题,计科 - TC工作室 A C D J题
  • 题目难度:

签到题:F G H
防 A K 题: E J
其余题目均为一般题

问题A:有趣的数字

题意:

输入n和k,问你是否可以将n这个数拆分成k个不同的奇数。

思路:

这题首先告诉我们要拆分成k个不同的奇数,那意味着从1开始算k个奇数是满足条件时n最小的情况。根据等差数列的前n项和可知,前k个奇数的和为k * k。如果k * k==n时,这时候刚好满足条件,k * k>n时必定不满足,k * k<n时,我们先讨论的是拆分成k个奇数的n最小的情况,如果n大于k * k,我们只需要满足n-k * k是一个偶数,那么就可以在其原先选定的奇数上加上多余的偶数,还是保证了选定的数为奇数,所以当n-k * k是一个偶数,则可以拆分,为奇数时,不能拆分。

#include<stdio.h>
int main()
{
    long long n, k;
    scanf("%lld%lld", &n, &k);//输入n和 k
    if (k * k == n)//奇数的前n项和的公式是k*k,
    {
        printf("Yes\n");
    }
    else if (k * k > n)//如果前k个奇数的和都比n大,那必定不可能拆分
    {
        printf("No\n");
    }
    else
    {
        if ((n - k * k) % 2 == 0)//如果大于前k个奇数的和,判断n-k*K的奇偶,如果n-k*k为偶数的话,那么就可以在前k个奇数里面加上,加上之后还是奇数。
        {
            printf("Yes\n");
        }
        else
        {
            printf("No\n");
        }
    }
    return 0;
}

问题B:峨峨天一柱

题意:

输入一个n,代表不同大小尺寸的orz。打印出n尺寸大小的orz。

思路:

这道题目没什么好说的,就是找规律,找不出来私聊我。

#include <stdio.h>

int main()
{
	int n, i, t;
	scanf("%d", &n);
	for (i = 0; i < n + 3; i++)
	{
		if (i == 0 || i == n + 2)
		{
			printf("   ");
			for (t = 0; t < n + 1; t++)
			{
				printf("* ");
			}
			printf("   *");
			if (i == 0)
			{
				printf("   ");
				for (t = 0; t < n; t++)
				{
					printf("* ");
				}
				printf(" ");
			}
			else
			{
				for (t = 0; t < 6 + (n - 1) * 2; t++)
				{
					printf(" ");
				}
			}
			for (t = 0; t < 2 + n; t++)
			{
				printf("* ");
			}
			printf("*");
		}
		else
		{
			printf(" *");
			for (t = 0; t < 5 + (n - 1) * 2; t++)
			{
				printf(" ");
			}
			printf("*  *");
			if (i == 1)
			{
				printf(" *");
				for (t = 0; t < 8 + (n - 1) * 4; t++)
				{
					printf(" ");
				}
			}
			else
			{
				for (t = 0; t < 8 + (n - 1) * 4 - (i - 2) * 2; t++)
				{
					printf(" ");
				}
			}
			printf("*");
		}
		printf("\n");
	}
	return 0;
}
#include<stdio.h>
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n + 3; i++)
    {
        for (int j = 0; j < 6 * n + 18; j++)
        {
            if ((j == 1 && i != 0 && i != n + 2) || (j == (n + 3) * 2 - 1 && i != 0 && i != n + 2) ||
                (i == 0 && j >= 2 && j < (n + 3) * 2 - 1 && j % 2 == 1) ||
                (i == n + 2 && j >= 2 && j < (n + 3) * 2 - 1 && j % 2 == 1) ||
                (j == (n + 3) * 2 + 2) ||
                (j >= (n + 3) * 2 + 6 && j <= (n + 3) * 2 + 5 + n * 2 && i == 0 && j % 2 == 0) ||
                (i == 0 && j >= (n + 3) * 2 + 5 + n * 2 + 2 && j % 2 == 1) ||
                (i == n + 2 && j >= (n + 3) * 2 + 5 + n * 2 + 2 && j % 2 == 1) ||
                (i != 0 && i != n + 2 && j >= (n + 3) * 2 + 5 + n * 2 + 2 && j == 6 * n + 18 - 2 * i - 1) ||
                (i == 1 && j == (n + 3) * 2 + 4))
            {
                printf("*");
            }
            else if (i != 0 && i != n + 2 && j > 6 * n + 18 - 2 * i - 1)
            {
                printf("");
            }
            else
            {
                printf(" ");
            }
        }
        printf("\n");
    }
    return 0;
}

问题C:Calling you

题意:

输入一个n,m,z。问你在1~z这个时间点中有多少个时间点是既是n的倍数又是m的倍数。

思路:

这道题目有两种方法,第一种是利用for循环从1到z依次遍历每一个时间点,如果有一个时间点同时能够被n和m整除的话,就是满足条件的点。(数据加强了,这种方法会直接被卡TE)还有一种方法是要判断一个数字能不能被n和m整数,是不是在1~z中,有多少个数是n和m的最小公倍数的倍数,那么我们就可以先求出n和m的最小公倍数,然后再用z除以n和m的最小公倍数即可。求最大公约数和最小公倍数,具体百度辗转相除法

方法一(不能AC补题赛的题目)

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

方法2

#include<stdio.h>

int n,m,z;

int main()
{
    scanf("%d%d%d",&n,&m,&z);
    int tn = n;
    int tm = m;
    while(tn != tm)
    {
        if(tn > tm)
            tm += m;
        else
            tn += n;
    }
    printf("%d",z/tn);
    return 0;
}
#include <stdio.h>

int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a % b);
}

int lcd(int a, int b)
{
    return a / gcd(a, b) * b;
}

int main()
{
    int n, m, z;
    scanf("%d%d%d", &n, &m, &z);
    printf("%d", z / lcd(n, m));
}
//最大公因数普通算法
int gcd(int m,int n)
{    
    int t,r;    
    if (m<n)//为了确保是大数除小数    
    {        
        t=m;        
        m=n;       
        n=t;    
    }    
 
    while((m%n)!=0)//辗转相除    
    {        
        r=m%n;        
        m=n;        
        n=r;    
    }   
 
    return n;
}

问题D:齐天大圣和七仙女

题意:

多组输入,输入一个n,代表悟空吃到第n天剩下一个桃子,求第一天的时候有多少个桃子,每天吃掉前一天剩下的一半多一个。

思路:

这其实就是求他的逆过程,你每天吃前一天剩下的一半多一个,那么你前一天的数量应该是比你当天的数量+1之后乘2,然后就不断的求它的逆过程即可。

#include <stdio.h>
int main()
{
    int n;
    while (scanf("%d", &n) != EOF)
    {
        int sum = 1;
        while (n > 1)
        {
            sum = (sum + 1) * 2;
            n--;
        }
        printf("%d\n", sum);
    }
    return 0;
}

问题E:签到题
看这个题解应该更好理解一点

#include <stdio.h>

int main()
{
    int n, k;
    scanf("%d%d", &n, &k);
    if (k % 3 != 0)
    {
        if (n % 3 != 0)
            printf("xue zhang jiu zhe a?");
        else
            printf("xue zhang tql!");
    }
    else
    {
        n %= k + 1;
        if (n == k || n % 3 != 0)
            printf("xue zhang jiu zhe a?");
        else
            printf("xue zhang tql!");
    }
}

问题F:邀月常相思
真签到题,输入一个t,代表t组输入,每组输入一个a和b,输出a*b。(唯一要注意的是a,b虽然在int数据范围里面,但是a * b 是超了int的数据范围的)

#include <stdio.h>

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        long long a, b, sum;
        scanf("%lld%lld", &a, &b);
        sum = a * b;
        printf("%lld\n", sum);
    }
}

问题G:百死百生来

题意:

这道题目水了,实际是让你们比较两个字符串是否相等,因为a,b的数据范围是明显超过了long long 。

思路:

思路就是输入两个字符串a,b,先判断两个字符串的长度是否相等,如果字符串长度都不相等,那两个数一定不相等,如果两个字符串长度相等,然后依次判断每位,如果出现一位不同,那么就肯定不相同,将其标记,遍历结束后如果被标记过,那么就不相同,如果没有被标记过,那么就相同。

#include<stdio.h>
#include<string.h>
char a[10000];
char b[10000];

int main()
{
	int flag = 0;
	scanf("%s%s", a, b);
	int len1 = strlen(a);
	int len2 = strlen(b);
	if (len1 == len2)
	{
		for (int i = 0; i < len1; i++)
		{
			if (a[i] != b[i])
			{
				flag = 1;
			}
		}
		if (flag == 1)
		{
			printf("No");
		}
		else
		{
			printf("Yes");
		}
	}
	else
	{
		printf("No");
	}
}

问题H:别看了从这往下都没法做,开始挂机吧
签到题*2,直接复制粘贴样例输出即可

#include <stdio.h>
int main()
{
    printf("Hellow world!");
}

问题I:睡觉那点事

题意:

题目意思就是输入一个n,代表有n个数,接着输入n个数,这n个数当中把奇数位进行编号从小到大排序,对偶数位进行编号从大到小排序,然后输出。

思路:

这道题目的思路基本就是把奇数位上的数字存到一个数组,偶数位的数字存到另一个数组。然后把这两个数组一个进行从小到大排序,一个从大到小排序。然后在依次输出两个数组,利用if来判断奇数位还是偶数位,然后在奇数位置上输出奇数,偶数位上输出偶数。

#include <stdio.h>
#include <algorithm>

using namespace std;
long long a[10005];
long long b[10005];
long long mp[10005];

bool cmp(long long x, long long y)
{
    return x > y;
}

int main()
{
    int n;
    scanf("%lld", &n);
    long long i, j;
    long long cnt1 = 0;
    long long cnt2 = 0;
    for (i = 1; i <= n; i++)
    {
        scanf("%lld", &mp[i]);
        if (i % 2 == 1)
        {
            a[cnt1] = mp[i];
            cnt1++;
        }
        else
        {
            b[cnt2] = mp[i];
            cnt2++;
        }
    }
    sort(a, a + cnt1);
    sort(b, b + cnt2, cmp);
    long long p = 0;
    cnt1 = 0;
    cnt2 = 0;
    for (i = 1; i <= n; i++)
    {
        if (i % 2 == 1)
        {
            if (p == 0)
            {
                p = 1;
                printf("%lld", a[cnt1]);
            }
            else
            {
                printf(" %lld", a[cnt1]);
            }
            cnt1++;
        }
        else
        {
            if (p == 0)
            {
                p = 1;
                printf("%lld", b[cnt2]);
            }
            else
            {
                printf(" %lld", b[cnt2]);
            }
            cnt2++;
        }
    }
    return 0;
}

问题J:二次元绘图

题意:

题目意思很简单,就是找不同的符号种类

思路:

这道题目有点子超钢,利用了文件的读入读出,先把这些字符存到文件中,然后读取文件,遍历每个字符,利用桶排的思想来判断每种字符出现的次数即可。当然你们眼睛看当然也可以。

#include <iostream>
#include <string>
#include <algorithm>
#include <cstdio>
#include<map>
using namespace std;

map<char,int>mp;
string temp;
int ans = 0;
int main()
{
	freopen("a.txt", "r", stdin);
	while (cin >> temp)
	{
		for (int i = 0; i < temp.size(); i++)
			if (mp[temp[i]] == 0)
			{
				ans++;
				mp[temp[i]] = 1;
			}
	}
	cout << ans;
    cout<<53<<endl;
	return 0;
}
  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

kunyuwan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值