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;
总结一下大概有以下几点:
- 没有认真审题。开始匆忙浏览了一下题干就开始写,没注意到是只有在干燥的地面时衣服才会变干(想想这不是常识吗?!),导致后面的修改导致整体逻辑不清晰。
- 循环嵌套时,重复定义i。这也是老生常谈的细节问题了,j、i常常傻傻分不清~;
- 开始思路过于复杂混乱,这也可归于第一点。又定义了一个数组用来判断每件衣服走过的路面的距离,如果等于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-时间问题
(略)