一些闲话
这次隔了这么久才更这一次线上赛,其实中间有一丢丢原因,我先在这里甩个锅。其一是上次线上赛没参加(不要和我提转普通练习),去参加了志愿者活动(心中有党);其二是其实这次线上赛也有两题没过,琢磨了半天还是runtime或者memory limit。但想了想还是先把这次的WIP发出来,接受指导与建议。
第一题:字符串替换
把字符串s中的前m个字符c替换成字符串d。
输入一个正整数n,表示测试案例的数量。
每组案例由一个字符串s,一个正整数m,一个字符c,一个字符串d组成。(保证s里至少会有m个c字符)
输出
针对每组案例,输出一个字符串,表示根据描述变化后的字符串。
每组案例输出完都要换行。
没什么好说的,找出来,换一下,输出来。
#include <iostream>
#include<string>
using namespace std;
int main()
{
int m, n,i;
string a, b; char c;
cin >> n;
while (n--)
{
cin >> a >> m >> c >> b;
for (i = 0; i < a.length(); i++)
{
if (a[i] == c&&m!=0)
{
cout << b; m--;
}
else cout << a[i];
}
cout << endl;
}
}
第二题:大柱的乘法
大柱规定了一种特别的乘法:当两个数相乘时,列竖式计算;如果位数不同,则通过高位补0的方式对齐;运算时,每个数位分开计算,相同数位上下两个数字相乘,取乘积的个位数作为该数位的值。例如:
这道题就按照题意实现即可,依位数补完再相乘即可。
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
int main()
{
int m, n, k;
string a, b,t; char c;
cin >> n;
while (n--)
{
cin >> a >> b; t = "";
int j = b.length() - 1;
for (int i = a.length() - 1; i >= 0 ; i--)
{
t += char((((a[i] - '0')*(b[j] - '0')) % 10)+'0');
j--;
if(j<0)break;
}
int k = 0;
for (int i = t.length() - 1; i >= 0; i--)
{
if (t[i] != '0'&&k==0)
{
k = 1; cout << t[i];
}
else if(k==1) cout << t[i];
}
if (k == 0)
cout << 0;
cout << endl;
}
return 0;
}
第三题:谁是卧底
曹操因为“鸡肋”口令杀了杨修之后,觉得拿某个名词当口令太容易让文官们胡思乱想,所以使用了一个整数当口令,见面时喊这个整数来表明是自己人而不是敌方间谍。然而后来又遇到了个问题,士兵们记性不好,无法准确记住这个整数,于是曹操规定,只要喊的数字能和口令相差10之内(包括10)都算对,这下子所有士兵都能喊出正确范围内的口令。有一天来了个蜀国的间谍混入了士兵中,曹操为了能分清总共m名士兵中,究竟谁是间谍,就让他们各自在纸上写下口令,同时交上来。假设魏国的士兵都各自写出了正确范围内的一个口令,而唯一一个蜀国的间谍是乱写的。这时曹操的头风病犯了,自己不记得口令是多少了,而且曹操生性多疑,不相信别人告诉他的口令。
问:曹操是否有可能根据士兵们交上来的口令,就能明确断定出谁是间谍?
输入
一个正整数n,表示n组案例。
每组案例先是一个正整数m(2<=m<=10000),表示连同间谍在内一共有m名士兵。然后是m个整数,分别表示第1、2、…、m名士兵写的口令。案例保证最多只会有一名间谍。
输出
针对每组案例,如果无法区分谁是间谍,则输出Cannot;如果能找出间谍,则输出间谍是第几个士兵(士兵编号从1到m)。
每组案例输出完都要换行。
关于这道题,其实我是有些疑惑的,比如5,20,20,20,35是不是Cannot,但后来听说好像不需要考虑这种可能。所以就是所有的数快排一下,然后要么最大要么最小,判断哪个是卧底。
#include <iostream>
#include<algorithm>
#include<cmath>
using namespace std;
struct s
{
int id, num;
};
int main()
{
int n;
cin >> n;
while (n--)
{
int m,k;
cin >> m;
if (m > 2)
{
s x[m];
for (int i = 0; i < m; i++)
{
x[i].id = i + 1;
cin >> x[i].num;
}
for (int i = 1; i < m; i++)
{
for (int j = 0; j < i; j++)
{
if (x[j].num>x[i].num)
swap(x[i], x[j]);
}
}
if (x[m - 1].num - x[0].num <= 20)
cout << "Cannot";
else
{
if (x[m - 1].num - 20 > x[1].num)
cout << x[m-1].id;
else cout << x [0].id;
}
cout << endl;
}
else
{
while (m--)
cin >> k;
cout << "Cannot" << endl;
}
}
return 0;
}
第四题:货郎担
星星用扁担挑了一摊货去赶集。货物一共有10件,每件货物都有一定的重量。扁担的两边各吊着一个筐,筐中可以装任意多件货物。星星希望两个筐中的货物重量差距尽可能小,以方便挑担时保持平衡。问该重量差距最小是多少?
这道题应该是背包的变形,同时因为案例比较小也可以用dfs做,但是不知道为什么,我就是re转mle。
丢脸,不发代码了。
第五题:字符串出现次数
看看a字符串里出现了多少次b字符串,规定如果多个b字符串在a中的位置出现重叠,则都不计入次数。
例如abababa里计算出现了多少次的aba时,由于所有的aba字符串都存在与别的aba字符串位置重叠,所以一共出现0次。
这个题也比较基础,就是找出来b字符串后把他的位置存好,和后一个比较是否小于b的长度。
#include<iostream>
#include<string>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
string a,b;
cin>>a>>b;
int B=b.length();
int r=-B-1;
int sum=0;
for(int i=0;i<a.length();i++)
{
if(a.substr(i,B)==b)
{
if(sum==1&&i-r<B)
{
sum--;
}
if(i-r>=B)
{
sum=sum+1;
}
r=i;
}
}
cout<<sum<<endl;
}
}
第六题:三英战大柱
有m个勇敢的学弟想要线下赛组队挑战大柱,规则上至多只允许3个学弟组队。黄大佬作为学弟的精神领袖,想要暗地帮助学弟组队,以达到最好的效果,即把所有题目都做出来。这m个学弟分别把所有题目的解题思路告诉了黄大佬,黄大佬记下了每个学弟按照解题思路是否可以做对每道题。然后黄大佬根据掌握的情况,想看看是否能够选出3个学弟,使得每道题都至少有其中一个学弟能做对。
输入
一个正整数n,表示有n组案例。每组案例先是两个正整数m和p,分别表示学弟的数量和题目的数量(3<=m<=10, p<=500000)然后是m行数据,每行数据由p个字符组成,其中第i行第j个表示第i个学弟第j题做对还是做错了。字符含义如下:A——正确,W——答案不对,T——超时,M——超内存,不会有除此之外的其它字符,每个字符之间有个空格,只有A表示做对。
输出
针对每组案例,如果能够选出3个学弟,使得每道题都至少有其中一个学弟能做对,那么输出Yes,否则输出No。每组案例输出完都要换行。
这题我也还没a出来,也是可以实现但是mle,但这题还是贴一下代码,以供参考,因为案例比较小,所以我直接三重循环了。
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
int m, p;
cin>>m>>p;
int x[m][p];
for(int i=0;i<m;i++)
{
for(int j=0;j<p;j++)
{
char a;
cin>>a;
if(a=='A')x[i][j]=1;
else x[i][j]=0;
}
}
int sum=0;
for(int i=0;i<m;i++)
{
for(int j=0;j<m&&j!=i;j++)
{
for(int k=0;k<m&&k!=i&&k!=j;k++)
{
int b=1;
for(int c=0;c<p;c++)
{
if(x[i][c]+x[j][c]+x[k][c]==0)
{
b=0;
}
}
if(b==1)sum=1;
}
}
}
if(sum)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
这时候还是runtime,因为我用的dev所以直接定义x[m][p],虽然这样肯定不规范。
#include<iostream>
using namespace std;
int main()
{
int n;
cin >> n;
while (n--)
{
int m, p;
m = 10; p = 500000;
bool **x = new bool*[m];
for (int i = 0; i < m; i++)
{
x[i] = new bool[p];
}
for (int i = 0; i<m; i++)
{
for (int j = 0; j<p; j++)
{
char a;
a = 'A';
if (a == 'A')x[i][j] = 1;
else x[i][j] = 0;
}
}
bool sum = 0;
for (int i = 0; i<m; i++)
{
for (int j = 0; j<m&&j != i; j++)
{
for (int k = 0; k<m&&k != i&&k != j; k++)
{
bool b = 1;
for (int c = 0; c<p; c++)
{
if (x[i][c] + x[j][c] + x[k][c] == 0)
{
b = 0;
}
}
if (b == 1)sum = 1;
}
}
}
if (sum)cout << "Yes" << endl;
else cout << "No" << endl;
for (int i = 0; i < m; i++)
{
delete[] x[i];
}
delete x;
}
return 0;
}
但是当我这样new了一个二维数组然后delete掉的时候,又变成了mle,就很难受。
还有一点闲话
就是因为这次线上赛是这学期最后一次,所以可能下学期再更,也有可能寒假随缘更。希望发现我的bug的大佬(如果有空的话)可以评论或者+q309894263讨论!(第四题用vector炸了)