记:第二次线上赛(二)

1. 线上赛打卡题3-星号阵列

描述
输出一个边长为 m 的正六边形。

输入
一个正整数 m 代表正六边形的边长。(2 <= m <= 20)

输出
一个边长为 m 的正六边形,每行最后一个星号后面没有空格,最后一行输出完成以后也要换行。

样例输入
3

样例输出
在这里插入图片描述

#include<iostream>
using namespace std;
int main()
{
	int m;
	cin >> m;
	//每一行第一个,最后一个星号位置
	int start = m, end = 2 * m-1;
	for (int i = 1; i <= 2 * m - 1; i++)
	{
		for (int j = 1; j <= end; j++)
		{
		    //第一行和最后一行在两个位置中输出星号
			if (i == 1 || i ==2*m-1)
			{
				if (j >= start && j <= end)
				{
					cout << "*";
				}
				else
				{
					cout << " ";
				}
			}
			//其他行,只在这两个点输出星号,否则输出空格
			else
			{
				if (j == start || j == end)
				{
					cout << "*";
				}
				else
				{
					cout << " ";
				}
			}			
		}
		if (i < (2 * m - 1) / 2 + 1)
		{
			start--;
			end++;
		}
		else
		{
			start++;
			end--;
		}
		cout << endl;
	}
	return 0;
}                

2. 数字陷阱

描述
小调为了练习自己的加法能力,随便想了两个正整数a和b,然后以a为第一个数字,加上b的值构成第二个数a+b,继续加b构成第三个数a+2b,每次都是在现有计算结果之上加上b。

但小调记不住太大的数字,所以一旦某次计算结果大于c,那么就立即把计算结果减去c,作为该次真正的结果。

小调决定一口气算到出现重复的数字为止。问最先与之前的某一次计算结果相同的数字是第几个数字。

输入
一个正整数n,表示案例的数量。(n<=100)

每组案例由3个正整数a、b、c组成。(a<=1000000000, b<=1000000000, c<=1000000000, a<=c, b<=c)

输出
针对每组案例,输出一个正整数,表示最先与之前的某一次计算结果相同的数字是第几个数字。

每组案例输出完都要换行。

分析:对题目进行数学分析,“问最先与之前的某一次计算结果相同的数字是第几个数字”,其实就是问:第几个数字与第一个数字(也就是a)相同。因为a的值每次增长b,而a又要在大于c的时候减去c,所以得出一个结论:出现与a相同的数字的时候,也就是刚好a加上了某个倍数的b,恰好使得这些加上的b,与c的值相同。
以上是对于c是b的整数倍的情况。倘若c并非b的整数倍,
举例:a=1,b=3,c=10
从第一个数开始: 1 4 7 10 3 6 9 2 5 8 1
周期为10。
为什么是10呢?
这是因为只有c乘以3=30之后,c才能凑成b的整数倍,周期即30/3=10。
因此,要使b乘以某个数是c的整数倍,b乘上这个数之后就是b和c的最小公倍数,这个数也就是周期,它的值等于Lcm(b,c)/b。
又因为Lcm(b,c)=b*c/Gcd(b,c),所以Lcm(b,c)=c/Gcd(b,c)。

还要注意一点:因为题目问的是第几项与第一项相同,因此求出周期之后+1才是最后的正确答案。

代码:

#include<iostream>
using namespace std;
int getGcd(int a, int b)
{
	int t = 1;
	while (t)
	{
		t = a % b;
		a = b;
		b = t;
	}
	return a;
}
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		int a, b, c;
		cin >> a >> b >> c;
		cout << c / getGcd(b, c) + 1<< endl;
	}
	return 0;
}        

3. 屋檐之下

描述
小调去商业步行街买了m件女装(初始都是干燥的),都买好以后天降大雨,小调没有带伞。

商业街一共有a米,依次给每一米编号,分别为第1米、第2米、…、第a米。商业街有的地方处于屋檐之下不会淋到雨,有的地方上方没有屋檐,会被雨淋湿。小调要从商业街的一端走到另一端(从第1米走到第a米)。

小调是个很怕被雨淋湿的人,所以每当经过一处没有屋檐的地方,小调就会将一件干燥的女装顶在头上充当雨伞。

女装在走过1米没有屋檐的地方之后就会被淋湿,淋湿的女装不能充当雨伞。一件淋湿的女装在经过b米没有雨的路面以后就会重新变回干燥的女装(可以由多段不连续、总长度是b米的干燥路面组成)。

问小调是否能够通过商业步行街?

输入
一个正整数n,表示案例的数量。(n<=20)

每组案例先是4个正整数m、a、b、c,其中m表示女装的件数,a表示商业街的长度,b表示女装由淋湿到干燥需要经历的干燥路面的长度,c表示屋檐的数量。(m<=100, a<=5000, b<=5000, c<=1000)

然后是c行数据,每行数据表示一个屋檐的起始到结束的范围,由两个正整数s和e组成,表示该屋檐从第s米开始,到第e米结束(1<=s<=e<=a),即第s米、第s+1米、…第e米的路面都是干燥的。屋檐和屋檐之间可能有重叠区域。

输出
针对每组案例,如果小调能通过商业步行街,那么输出Yes,否则输出No。

每组案例输出完都要换行。

分析:简单的模拟。。。然而这题花费了大半的时间依旧是WA;
总结一下大概有以下几点:

  1. 没有认真审题。开始匆忙浏览了一下题干就开始写,没注意到是只有在干燥的地面时衣服才会变干(想想这不是常识吗?!),导致后面的修改导致整体逻辑不清晰。
  2. 循环嵌套时,重复定义i。这也是老生常谈的细节问题了,j、i常常傻傻分不清~;
  3. 开始思路过于复杂混乱,这也可归于第一点。又定义了一个数组用来判断每件衣服走过的路面的距离,如果等于b时,再清空表示可用;否则如果小于b每走一步++;其实没有必要。状态数组不一定只能用1或者0来表示,也可以体现一种状态转变的过程。如此题中,就是用数值0->b来体现衣服的潮湿程度的变化:0表示潮湿程度为0,即完全干燥,用过之后彻底潮湿,变为b;此后,每经过一米干燥地面,潮湿程度减一,就巧妙地解决了这个模拟问题的关键之处。
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		int m, a, b, c;
		cin >> m >> a >> b >> c;
		int* cloth = new int[m + 1];
		for (int i = 1; i <= m; i++)
		{
			cloth[i] = 0;//0干燥,淋湿变为b
			//非0值每经过一米干燥地面就减1
		}
		bool* street = new bool[a + 1];//长度等于商业街
		for (int i = 1; i <= a; i++)
		{
			street[i] = false;//开始没有屋檐
		}
		while (c--)
		{
			int s, e;
			cin >> s >> e;
			for (int i = s; i <= e; i++)
			{
				street[i] = true;
			}
		}		
		int flag = true;//假设可以通过,遇到没衣服改为false
		for (int i = 1; i <= a; i++)
		{
			if (street[i]) //街道干燥
			{
				for (int j = 1; j <= m; j++)
				{
					if (cloth[j] > 0)//湿的衣服慢慢变干!
					{
						cloth[j]--;
					}
				}
			}
			else//街道潮湿
			{
				bool f = false;
				for (int j = 1; j <= m; j++)
				{
					if (cloth[j] == 0)//找到一件能用的衣服
					{
						//改成b是为了经过b米后刚好变为0干燥
						cloth[j] = b;
						f = true;
						break;
					}					
				}
				if (!f)
				{
					flag = false;
					break;
				}
			}
		}
		if (flag)
		{
			cout << "Yes";
		}
		else
		{
			cout << "No";
		}
		cout << endl;
	}
	return 0;
}

4. 女装大佬-2

描述
小调从商业步行街买回了m件女装,然后为每件女装依次编号为1、2、…、m。

小调在第1天喜欢所有买回的m件女装。

第2天情况有所变化,小调对所有编号是2的倍数的女装(2、4、6、…)的态度都发生了改变。注:态度改变的定义是,如果原先是喜欢那么变成不喜欢,如果原先是不喜欢那么变成喜欢。

第3天小调对所有编号是3的倍数的女装的态度都发生了改变。

以此类推,到了第m天,小调对所有编号是m的倍数的女装的态度都发生了改变。

问m天之后,小调喜欢的女装有多少件?

输入
一个正整数n,表示案例的数量。(n <= 100)

每组案例由一个正整数m组成,m表示女装的总件数。(m <= 1e6)

输出
针对每组案例,输出一个整数,表示m天之后小调喜欢的女装有多少件。

每组案例输出完都要换行。

分析:与数的因子个数有关。如4的因子个数为3,4在第1,2,4天各被翻一次(第一天是翻成喜欢),因为翻了奇数次,所以最后还是喜欢。得出结论:因子个数为奇数的数最后为喜欢,因子个数为偶数的数最后是不喜欢。又因为只有完全平方数的因子为奇数,也就是只需要判断m中有多少个完全平方数即可。
注意sqrt需取整。

代码:

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		int m;
		cin >> m;
		cout << (int)sqrt(m) << endl;
	}
	return 0;
}        

5. 一二三

描述
小调发现,可以找出3个三位数,它们的大小比例是1:2:3,并且这3个三位数各个位置上一共9个数字都没有重复。

找到所有满足条件的数字。

输入

输出
按照从小到大的顺序,输出所有满足这样条件的3个三位数。

每组3个三位数两两之间都有一个空格字符,每组输出完都要换行。

分析:用状态数组标记各个位置上的数字有没有出现过。暴力循环即可

注意是包括0的十个数字,而不是1->9九个数字,当然0不能放在开头。

#include<iostream>//一二三
using namespace std;
bool f(int s[],int a)
{
	bool flag = true;
	int b[3];//保存a各个位置上的数字
	b[0] = a / 100;
	b[1] = a / 10 % 10;
	b[2] = a % 10;
	for (int i = 0; i < 3; i++)
	{
		if (s[b[i]]==1)
		{
			flag = false;
			break;
		}
		s[b[i]] = 1;
	}
	return flag;
}
int main()
{
	for (int i = 102; i <= 329; i++)
	{
		int a = i, b = 2 * i, c = 3 * i;
		int s[10] = { 0 };//每次对a,b,c判断有无重复的数字
		bool flag1, flag2, flag3;
		flag1 = f(s, a);
		flag2 = f(s, b);
		flag3 = f(s, c);
		if (flag1 && flag2 && flag3)
		{
			cout << a << " " << b << " " << c<<endl;
		}
	}
	return 0;
}

6. 线上打卡题4-时间问题

(略)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值