ACM寒假集训第一次专题任务
ACM寒假集训第一次专题任务
一、
题目:Long Loong


解题思路:
因为o出现次数由输入的x所决定,可以想到使用一个循环解决。
AC代码:
#include<iostream>
using namespace std;
int main()
{
int X;
cin>>X;
cout<<"L";
for(int i=1;i<=X;i++)
{
cout<<"o";
}
cout<<"ng";
system("pause");
return 0;
}
二、
题目:YES or YES?

解题思路:
使用循环将t个字符串全部输入字符串数组并全部转换成小写后与”yes“进行比较。
AC代码:
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{
int t;
cin>>t;
getchar();
string s[t+1];
for(int i=0;i<t;i++)
{
getline(cin,s[i]);
for(int j=0;j<3;j++)
{
s[i][j]=tolower(s[i][j]);
}
}
for(int i=0;i<t;i++)
{
if(s[i]=="yes")
{
cout<<"YES"<<endl;
}
else
{
cout<<"NO"<<endl;
}
}
system("pause");
return 0;
}
注意:
cin在读取字符串时,会跳过前导的空白字符(像空格、制表符、换行符),并且在遇到下一个空白字符时停止读取。cin 会把换行符留在输入缓冲区里。这可能会对后续使用 getline 读取输入造成影响。(可在getline之前用cin.ignore()清除输入缓冲区里的换行符)
getline 是一个函数,定义于 <string> 头文件中。它会从输入流里读取一行内容,直至遇到换行符为止,并且会把换行符从输入缓冲区中移除。
三、
题目:Even? Odd? G


解题思路:
因为要判断的正整数可能很长,所以用字符串数组接收。通过字符串最后一位数字判断奇偶(查ASCII表可知偶数对应ASCII码也为偶数,可以直接判断)。
AC代码:
#include<string>
using namespace std;
int main()
{
int N;
cin>>N;
cin.ignore();
char n[110];
string s[110];
for(int i=0;i<N;i++)
{
cin>>s[i];
n[i]=s[i].back();
}
for(int i=0;i<N;i++)
{
if(n[i]%2==0)
{
cout<<"even"<<endl;
}
else
{
cout<<"odd"<<endl;
}
}
return 0;
}
四、
题目:Problem Generator


解题思路:
t确定几轮测试,每轮测试需要明确比赛轮数m和代表题目的字符串a(n看起来可有可无),遍历a并统计每个难度出现的次数,再判断每个难度次数是否达到要求。统计题目缺少个数并记入数组,测试循环结束后遍历数组输出。
AC代码:
#include<iostream>
#include<string>
#include <algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
int sum[1010]={0};
for(int i=0;i<t;i++)
{
int n,m,c[7],T;
fill(c,c+7,0);
cin>>n>>m;
string a;
cin>>a;
for(auto p=a.begin();p!=a.end();p++)
{
if(*p=='A')
{
c[0]++;
}
else if(*p=='B')
{
c[1]++;
}
else if(*p=='C')
{
c[2]++;
}
else if(*p=='D')
{
c[3]++;
}
else if(*p=='E')
{
c[4]++;
}
else if(*p=='F')
{
c[5]++;
}
else if(*p=='G')
{
c[6]++;
}
}
for(int j=0;j<7;j++)
{
T=m-c[j];
if(T>0)
{
sum[i]+=T;
}
}
}
for(int i=0;i<t;i++)
{
cout<<sum[i]<<endl;
}
return 0;
}
注意:
1、迭代器for(auto p=a.begin();p!=a.end();p++)。
这种迭代器遍历方式适用于所有提供了 begin() 和 end() 成员函 数的容器,例如 std::vector、std::list、std::set 等。
2、std::fill 函数定义于 <algorithm> 头文件中
原型:void fill( ForwardIt first, ForwardIt last, const T& value );
first:指向要填充元素范围起始位置的迭代器。
last:指向要填充元素范围结束位置的下一个位置的迭代器。
value:要赋给指定范围内每个元素的值。
fill(c, c + 7, 0); 的具体分析
c:在 C++ 里,数组名可以隐式转换为指向数组首元素的指针,所以c相当于指向数组c第一个元素的指针,也就是迭代器。c + 7:指针算术运算,它指向数组c第 7 个元素之后的位置。0:要赋给数组元素的值。
五、
题目:rules


解题思路:
直接将题目翻译成编程语言可得
AC代码:
#include<iostream>
using namespace std;
int main()
{
int n,m,k,r,SUM=0;
cin>>n>>m>>k;
for(int i=0;i<m;i++)
{
int sum=0;
for(int j=0;j<n;j++)
{
cin>>r;
if(r==k)
{
sum++;
}
}
if(sum*2>=n)
{
SUM++;
}
}
if(SUM*2>=m)
{
cout<<"YES"<<endl;
}
else
{
cout<<"NO"<<endl;
}
return 0;
}
六、
题目:Many Replacement



解题思路:
(直接翻译题目会超时)使用结构体数组构建映射表,将所有的置换操作按顺序输入;然后从'a'至'z'每一个字母都遍历一次映射表,并将此字母的变换终点[1]输入一个新的字符串fc[2],此字符串将作为最终的映射表承担对目标字符串S的变换任务。遍历S中的元素,并通过S[i]-'a'将S中的第i个元素转换成fc对应下标[3],将fc[S[i]-'a']输出。
AC代码:
#include<iostream>
#include<string>
using namespace std;
struct replace{
char fr;
char to;
};
int main()
{
int N;
string S;
int Q;
string fc;
replace c[200000];
cin>>N;
cin>>S;
cin>>Q;
for(int i=0;i<Q;i++)
{
cin>>c[i].fr>>c[i].to;
}
for(char io='a';io<='z';io++)
{
char o=io;
for(int i=0;i<Q;i++)
{
if(o==c[i].fr)
{
o=c[i].to;
}
}
fc[io-'a']=o;
}
for(int i=0;i<(int)S.size();i++)
{
cout<<fc[S[i]-'a'];
}
return 0;
}
七、
题目:更好的交换



解题思路:
(直接翻译题目会超时)所以观察示例1:
| 1 | 2 | 3 | |
|---|---|---|---|
| 1 | 4 | 5 | 6 |
| 2 | 3 | 2 | 1 |
| 3 | 9 | 8 | 7 |
经过变换:
| 1 | 3 | 2 | |
|---|---|---|---|
| 1 | 4 | 6 | 5 |
| 2 | 3 | 1 | 2 |
| 3 | 9 | 7 | 8 |
可知,变换不改变这些元素在二维数组中的下标(包括行列)。那么,只需要明确以上表格中加粗部分的最终位置即可确定最终表格。
先在输入数据的同时分别存储初始行列编号,tagx[1100]与tagy[1100]分别存储行列编号,下标为正常顺序,储存值为位于当前行(列)的行(列)[4]。再经过m次行(列)变换,直接遍历tagx[]与tagy[]即为所求表格。
AC代码:
#include<iostream>
#include <utility>
using namespace std;
int main()
{
int n,m,a[1100][1100]={0},tagx[1100],tagy[1100];
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
tagx[i]=tagy[i]=i;
}
for(int op,x,y,i=1;i<=m;i++)
{
cin>>op>>x>>y;
if(op==1)
{
swap(tagx[x],tagx[y]);
}
else
{
swap(tagy[x],tagy[y]);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(j!=1)
cout<<" ";
cout<<a[tagx[i]][tagy[j]];
}
cout<<"\n";
}
return 0;
}
注意:
std::swap 定义在 <algorithm> 或 <utility> 头文件中,在 C++11 及以后版本中,推荐包含 <utility> 头文件。
它接受两个同类型对象的引用作为参数,然后交换它们的值。
学习总结
语法:
cin在读取字符串时,会跳过空白字符,并且在遇到下一个空白字符时停止读取,且会把换行符留在输入缓冲区
getline 定义于 <string> 头文件中。它会从输入流里读取一行内容,直至遇到换行符为止,并且会把换行符从输入缓冲区中移除。
以上二者都不包含结束符。
C++语法糖:
一、auto的使用:
1、编译器会根据赋给变量的值自动推导变量类型(必须要赋值)
2、范围for循环for(auto ai : a)
二、Lambda表达式:
基本语法: [capture list] (parameter list) -> return type { function body }
捕获列表(capture list):用于指定 Lambda 表达式可以访问的外部变量。它可以为空,也可以包含一个或多个变量,变量之间用逗号分隔。捕获方式有值捕获和引用捕获两种。
参数列表(parameter list):与普通函数的参数列表类似,用于传递给 Lambda 表达式的参数。可以为空。
返回类型(return type):指定 Lambda 表达式的返回类型。如果 Lambda 表达式的返回类型可以由编译器自动推导得出,这部分可以省略。
函数体(function body):包含 Lambda 表达式要执行的代码。
例如:
#include <iostream>
int main() {
auto add = [](int a, int b) { return a + b; };
int result = add(3, 5);
std::cout << "3 + 5 = " << result << std::endl;
return 0;
}
中 auto add = [](int a, int b) { return a + b; };
时空复杂度:

时间复杂度默认指最大时间复杂度
空间复杂度是衡量程序内存占用的量度,它是变量定义次数的化简结果,采用和时间复杂度完全相同的记号和化简规则。
STL的使用:
1、sort:快速排序,时间复杂度O(nlog(n)),默认用小于号排序,区间左闭右开
2、reverse:翻转元素,时间复杂度O(n),区间左闭右开
3、lower_bound / upper_bound:二分查找,时间复杂度O(log(n))
lower_bound:在有序序列中二分查找「第一个大于等于给定值」的元素,并返回它的迭代器。
upper_bound: 用于查找「第一个大于给定值」的元素,用法与lower_bound相同。
4、常用的STL容器:pair
stack
queue
priority_queue
vector
deque
list
set
map
string

浙公网安备 33010602011771号