2018-2019赛季多校联合新生训练赛第七场补题和题解(中石油)

这次比赛我因为打了山师的比赛,两个比赛时间有一点冲突,所以就没打,是我打完山师以后才来看的这场比赛,总体来说我感觉这场比赛有的题难度不大,有的题卡超时挺烦的,必须想出不是常规的方法,这一点还挺难的,我现想是想不出来不,只能靠看别人的博客,学习别人的思路,做题的时候我发现了两道和以前做过的类似的题,然后我就使用了类似的方法来解决,发现满满的tle啊!我终于知道这个难度分级是怎么回事了 看来不优化不行啊 开始吧!

问题 A: 面积

题目描述

最近楠楠的数学老师在教他计算梯形面积,由于测验时他不小心计算错了一道求等腰梯形面积的题目,楠楠的老师要罚他计算N道这样的题,这太痛苦了!楠楠求你编个程序来帮助他快速计算面积。
已经知道每道题给如下图形状的等腰梯形中的A,B,C三个参数,请编程计算它的面积。

2018-2019赛季多校联合新生训练赛第七场补题和题解(中石油)_第1张图片

输入

一行3个正整数A,B,C,分别表示等腰梯形的上底宽、高和左边突出的长度(即下底宽为A+2C )。

输出

一行,一个整数,表示梯形的面积。

样例输入
复制样例数据 2 3 1

样例输出
9

这是一道基础编程题,就不多说了,上代码:

#include
using namespace std;
int main() {
  int a,b,c;
  cin>>a>>b>>c;
  cout<<((a+a+c+c)*b)/2;
}

问题 B: 网络信号

题目描述

楠楠来到科技馆参加一个网络信息探测试验活动。试验时中间有一个WiFi网络路由器,以路由器为中心半径为R的圆内(包括圆周上)的手机都可以收到网络信号,而圆外的手机就接收不到信号。楠楠拿着手机,一开始在中间,然后每次向左或向右走动一定距离,停下测试一下网络信号。问有多少次测试是可以接收到网络信号的。
例如:R=8米,楠楠一共测试了4次。第一次向左走3米;第二次向左再走4米;第三次向左再走2米;第四次向右再走12米,结果只有第3次测试楠楠是接收不到信号的,其它3次测试都可以接收到网络信号。

2018-2019赛季多校联合新生训练赛第七场补题和题解(中石油)_第2张图片

输入

第一行,2个正整数R和N。分别表示网络路由器的工作半径和楠楠的测试次数。
第二行,N个整数。第i个整数Di表示楠楠第i次向左或向右移动的距离,如果Di是负整数,则表示楠楠第i次测试是向左移动了|Di|米的距离。如果Di是非负整数,则表示楠楠第i次测试是向右移动了Di米距离。

输出

一个整数。表示楠楠有多少次测试是可以接收到网络信号的。

样例输入
复制样例数据 4 5
2 2 2 -8 -8

样例输出
3

提示

第1、2、4次都半径为4的圆内,所以可以接收信号

10个数据:R,N的范围是[1…100]。每次移动距离的范围是[-100…100]。

这题给了一个圆形看起来挺吓人的,其实就是一个一维的问题,只要判断当前位置是否越界就行了 代码:

#include
using namespace std;
int main() {
  int r,n;
  cin>>r>>n;
  int x;
  int sum=0;
  int ans=0;
  for(int i=0;i<n;i++) {
    cin>>x;
    sum+=x;
    if(sum>=(-r)&&sum<=(r))
    ans++;
  }
  cout<<ans;
}

问题 C: 排队I

题目描述

楠楠最近在研究南海区5年级英语成绩的排序有关算法,如果数列中的数是从小到大排列的,则称有序的。研究中对于没有排好序的数列,要统计每个数前面有多少比它大的数字。比如有5个数的数列: 3 1 4 2 5,则第1个数3之前有0个数比它大;第2个数1之前有1个数比它大;第3个数4之前有0个数比它大;第4个数2之前有2个数比它大;第5个数5之前有0个数比它大。由于数列很长,楠楠求你编程来统计。

输入

第一行1个整数N,表示数列有N个整数。
第二行有N个非负整数,每个数表示一个分数,范围是[0…120]。

输出

一行N个非负整数(每个非负整数后面有一个空格),第i个数表示原数列中第i位前有多少比第i位数大。

样例输入
复制样例数据 5
3 1 4 2 5

样例输出
0 1 0 2 0

提示

8个的数据: N的范围是[1…1000],每个数范围是[0…120]
2个的数据:N的范围是[1…1,00,000],每个数范围是[0…120]

这题就是我刚才前面说的做过的题用类似的方法做然后T的典型案例啊! 这题用两个for循环做的话时间好像4000+ms了 回去一看 发现数据量非常的大,用两个for确实会这样 后来看一个青理工大佬的方法,学会了一个很巧妙的方法,仔细思考后发现这个思路真的太巧秒了!还是技不如人啊 青理的老哥的号名字是qut201801 tql sdl wsl!
这里说一下思路:先用桶的思想开一个桶,然后输入x,a[x]++,直接从x+1开始找,如果找到就说明之前已经有比这一项大的数了,于是ans++,最后直接输出,在循环里不要忘记给ans赋初值~ 这样就达到了优化的目的,太强了!

#include
using namespace std;
int a[200];
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin>>n;
  int x;
  int ans;
  for(int i=0;i<n;i++) {
    cin>>x;
    a[x]++;
    ans=0;
    for(int j=x+1;j<=120;j++)
    ans+=a[j];
    cout<<ans<<" ";
  }
  return 0;
}

问题 D: 覆盖

题目描述

楠楠的学校有B个男生和G个女生都来到一个巨大的操场上,操场可以看成是N行M列的方格矩阵,如下图(1)是一个4行5列的方格矩阵。每个男生负责打扫一些连续的行,每个女生负责打扫一些连续的列。比如有两个男生,第一个男生负责第1、2两行、第二个男生负责第4行,如图(2)的蓝色。打扫的区域可能重复,比如,又有两个女生,第一个女生负责打扫第3、4两列,第二个女生负责打扫第4、5两列,如图(3)的红色。从图(3)可以容易看出,有颜色覆盖的方格数为18,即这4名学生总共打扫了18个方格。
老师要楠楠在学校给出打扫安排的数据后快速计算出这些学生总共打扫了多少方格?

输入

第一行4个正整数:N,M,B,G,N表示方阵行数,M表示方阵列数,B表示男生数,G表示女生数。
接下来B行,每行两个整数x y。表示相应某个男生负责打扫从第x行到第y行(共y-x+1行),保证1≤x≤y≤N。
再接下来G行,每行两个整数x y。表示相应某个女生负责打扫从第x列到第y列(共y-x+1列),保证1≤x≤y≤M。

2018-2019赛季多校联合新生训练赛第七场补题和题解(中石油)_第3张图片

输出

一个整数,表示所打扫的面积。

样例输入
复制样例数据 4 5 2 2
1 2
4 4
3 4
4 5

样例输出
18

提示

8个的数据:N,M,B,G的范围都是[1…100]
2个的数据:N,M,B,G的范围都是[1…5,000]

这题我跟着mhr大佬学了一下思路,思路是分成两种情况,开一个bk二维数组来存一下男生和女生打扫卫生的情况,然后最后判断一下男生是否有人干活,如果有人干活的话就分到了第一种情况,第一种情况先统计一下男生没有打扫的行数,然后ans+的时候就可以用列数乘以(总行数-没有打扫的行数)这样做的好处是方便下一步计算女生打扫的行数,因为女生再次打扫的话增加的打扫数量是男生没有扫到的行数,所以这样就挺方便的,就算刚开始统计的是男生打扫过的行数,到最后计算女生的时候还是得减一下,不如直接减了。第二种情况就是男生根本没干活我觉得挺真实的2333 这时候用行数乘以女生打扫的列数就是最后的答案,注意上面的二维数组存情况的时候不能有重叠的情况,所以我就都用了0 上代码!?

这里贴一下mhr大佬的博客~大家多多串门哦2333大佬的博客

#include
using namespace std;
int bk[5001][5001];
int main() {
  int n,m;
  int nan;
  int nv;
  int x,y;
  cin>>n>>m>>nan>>nv;
  for(int i=0;i<nan;i++) {
    cin>>x>>y;
    for(int k=x;k<=y;k++)
    bk[k][0]++;
  }
  for(int i=0;i<nv;i++) {
    cin>>x>>y;
    for(int k=x;k<=y;k++)
    bk[0][k]++;
  }
  int sum=0;
  int ans=0;
  if(nan>0) {
    for(int i=1;i<=n;i++)
    if(!bk[i][0])
    sum++;
    ans+=(n-sum)*m;
    for(int j=1;j<=m;j++)
    if(bk[0][j])
    ans+=sum;
  }
  else {
    for(int i=1;i<=m;i++)
    if(bk[0][i])
    ans+=n;
  }
  cout<<ans;
}

问题 E: 游戏

题目描述

今天是星期天,小楠楠来找你玩“石头、剪刀、布游戏”。你正在学习信息学,所以想了一种需要编程来玩的“石头、剪刀、布游戏”。首先,用数字1,2,3分别表示出石头、剪刀、布。其次,你确定自己前N次“石头、剪刀、布”的出拳方法,下面N次再次同样出拳,…,周而复始;也要求楠楠确定他前M次的出拳方法,然后周而复始。问第K次后,你赢了几次?
例如:N=4,你的前4次出拳方式是“石头、剪刀、布、布”,用数字表示即:”1 2 3 3”。M=5,楠楠前5次出拳方式是“剪刀、石头、石头、布、布” ,用数字表示即:”2 1 1 3 3”。K=10时,情况如下表:

你共赢了5次。

输入2018-2019赛季多校联合新生训练赛第七场补题和题解(中石油)_第4张图片

第一行3个整数N,M,K。分别表示你出拳方式的周期长度、楠楠出拳方式的周期长度和总共玩的次数。
第二行有N个整数,每个整数为1、2、3其中之一。
第三行有M个整数,每个整数为1、2、3其中之一。

输出

一个整数,表示K轮出拳后,你赢的次数。

样例输入
复制样例数据 5 6 100
1 3 2 2 1
3 3 1 1 1 2

样例输出
29

提示

8个数据: N,M 的范围是[1…100],K的范围是[1…100,000]。
2个数据: N,M的范围是[1…100],K的范围是[1…1,000,000,000]

这题也是以为我以为我做过然后用以前方法做的一道题!刚开始用暴力while 然后感觉没有错,因为以前那个宇宙大爆炸版的剪刀石头布也是这样做的,后来单门回去看了一下那个题的数据,发现那个题的数据是这样的:
【数据说明】
对于 100%的数据,0 < N ≤ 200,0 < NA ≤ 200, 0 < NB ≤ 200。
直接少了好几个数量级! 于是就想个办法优化一下:找到他们之间的最小公倍数,这就是他们的一个最小正周期,每一次经过这一个周期都会有一个固定的值,到最后让结果先加上几个正周期的结果,然后让总次数减去周期*周期个数,最后再单独算剩下的情况,加上就行了~~这里有点捞,没学过gcd只能用辗转相减太捞了不要在意哈哈哈哈哈 ~~

#include
using namespace std;
int a[20000];
int b[20000];
int main() {
  ios::sync_with_stdio(false);
  cin.tie(false);
  cout.tie(false);
  int n,m,t;
  cin>>n>>m>>t;
  for(int i=0;i<n;i++)
  cin>>a[i];
  for(int i=0;i<m;i++)
  cin>>b[i];
  int n1=n;
  int m1=m;
  while(1) {
    if(n1>m1)
    n1-=m1;
    else
    m1-=n1;
    if(n1==m1)
    break;
  }
  int zq=n*m/m1;
  int z=zq;
  int c=0;
  int d=0;
  int sum=0;
  while(z--) {
    if(a[c]==1&&b[d]==2||a[c]==2&&b[d]==3||a[c]==3&&b[d]==1)
    sum++;
    c++;
    d++;
    if(c==n)
    c=0;
    if(d==m)
    d=0;
  }
  int s,ans;
  if(t>=zq) {
    s=t/zq;
    ans=s*sum;
    t-=s*zq;
    while(t--) {
      if(a[c]==1&&b[d]==2||a[c]==2&&b[d]==3||a[c]==3&&b[d]==1)
      ans++;
      c++;
      d++;
      if(c==n)
      c=0;
      if(d==m)
      d=0;
      }
    }
    else  {
      ans=0;
      while(t--) {
      if(a[c]==1&&b[d]==2||a[c]==2&&b[d]==3||a[c]==3&&b[d]==1)
      ans++;
      c++;
      d++;
      if(c==n)
      c=0;
      if(d==m)
      d=0;
    }
  }
  cout<<ans;
}

这里分享一个超时的写法(我原先的写法) 看起来挺简洁的,可是就是被卡超时,有什么办法呢?只能重新写!

#include
using namespace std;
int a[1000];
int b[1000];
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,m,t;
  cin>>n>>m>>t;
  for(int i=0;i<n;i++)
  cin>>a[i];
  for(int i=0;i<m;i++)
  cin>>b[i];
  int c=0;
  int d=0;
  int sum=0;
  while(t--) {
    if(a[c]==1&&b[d]==2||a[c]==2&&b[d]==3||a[c]==3&&b[d]==1)
    sum++;
    c++;
    d++;
    if(c==n)
    c=0;
    if(d==m)
    d=0;
  }
  cout<<sum;
}

问题 F: 差

题目描述

楠楠在网上刷题,感觉第一题:求两数的和(A+B Problem)太无聊了,于是增加了一题:A-B Problem,难倒了一群小朋友,哈哈。
题目是这样的:给出N个从小到大排好序的整数,一个差值C,要求在这N个整数中找两个数A和B,使得A-B=C,问这样的方案有多少种?
例如:N=5,C=2,5个整数是:2 2 4 8 10。答案是3。具体方案:第3个数减第1个数;第3个数减第2个数;第5个数减第4个数。

输入

第一行2个正整数:N,C。
第二行N个整数:已经有序。注意:可能有相同的。

输出

一个整数,表示该串数中包含的所有满足A-B=C的数对的方案数。

样例输入
复制样例数据 4 1
1 1 2 2

样例输出
4

提示

5个数据:N的范围是[1…1,000]。
5个数据:N的范围是[1…100,000]。

所有数据:
C的范围是[1…1,000,000,000]。
N个整数中每个数的范围是:[0…1,000,000,000]。

这题也是学了青理工大佬的方法,看完以后感觉这不是人能想起来的方法啊!!!直接线性就做出来了!!!我感觉我再想个十年也想不出来这个方法,实在是太妙了! 十点了,天气冷,我睡了
这里讲一下这个题的思路:先开一个long long 的map当做无限的数组,然后输入x,再输入x的时候判断一下x-c是否大于0,如果大于0的话ans就加上mp[x-c](这一句的意思是ans加上x-c那一项 就是题目中的b 因为a-b=c可以转化成a-c=b)x-c如果大于0,就说明当输入x的时候 这时候x是a 如果要满足a-b=c的话,看一下这时候b有没有出现过(因为a-c=b)如果这个b出现过的话就让ans加上它那一项代表的值就行了,因为有下一步 下一步的意思是吧出现过的数和它出现的数量存起来
我也不知道我有没有讲的很明白,大体就是这个意思 我也想了半天应该怎么描述这件事情,如果讲的不清不楚的话请见谅咯 看一下mhr大佬的解释就行了

再次贴上大佬的博客,看不懂的话看大佬博客就行了

#include
using namespace std;
map<long long ,long long >mp;
int main() {
  int n,c;
  cin>>n>>c;
  int x;
  long long ans=0;
  for(int i=0;i<n;i++) {
    cin>>x;
    if(x-c>=0)
    ans+=mp[x-c];
    mp[x]++;
  }
  cout<<ans;
}

问题 G: 成绩统计

题目描述

六年级一班举办数学小竞赛。考试结束后,班主任老师让张红同学用计算机编程的方法,来统计一下班里N名同学在这次数学竞赛中,成绩在以下各类别的人数。
要求:分数为整数,用变量F表示,以百分制作为记分标准。成绩在(90≤F≤100)分数之间,用“you”来标识;成绩在(80≤F≤89)分数之间,用“liang”来标识;成绩在(60≤F≤79)分数之间,用“zhong”来标识;成绩在60分以下,则用“cha”来标识。

输入

共有两行:
第一行:包含一个整数 N,表示学生的数量(其中 1≤N≤30);
第二行:是 N 个用 1 个空格隔开的学生的分数(分数为整数)。

输出

共有四行:每行包括两项,第一项是标识符,第二项是统计该类别人数的数量,两项之间用 1 个空格隔开。

样例输入
复制样例数据 10
92 78 80 95 100 87 64 56 52 98

样例输出
You 4
Liang 2
Zhong 2
Cha 2

提示

按高分到低分的顺序来统计,每一行输出数据都从第一列开始。

这题直接边输入边计数就行了 代码:

#include
using namespace std;
int main() {
  int n;
  cin>>n;
  int a=0;
  int b=0;
  int c=0;
  int d=0;
  int x;
  for(int i=0;i<n;i++) {
    cin>>x;
    if(x>=90&&x<=100)
    a++;
    else if(x>=80&&x<=89)
    b++;
    else if(x>=60&x<=79)
    c++;
    else
    d++;
  }
  cout<<"You "<<a<<endl<<"Liang "<<b<<endl<<"Zhong "<<c<<endl<<"Cha "<<d;
}

问题 H: 打印图形II

题目描述

由键盘输入任意一个自然数 N,输出如下图:形如“沙漏”的由大写字母组成的图形。

输入

只有一个整数N,为图形上半部分的行数(其中2<=N<=26)

输出

输出图形,图形的最左侧从第一列开始输出。
2018-2019赛季多校联合新生训练赛第七场补题和题解(中石油)_第5张图片

这题使用了强制类型转换和’A’+1='B’的思路,注意一下打空格和每个for循环的含义就行了。

#include
using namespace std;
int main() {
  int n;
  cin>>n;
  for(int i=0;i<n-1;i++) {
    for(int j=0;j<i;j++)
    cout<<" ";
    for(int k=i;k<n;k++)
    cout<<char('A'+k);
    for(int l=n-2;l>=i;l--)
    cout<<char('A'+l);
    cout<<endl;
  }
    for(int i=0;i<n-1;i++)
    cout<<" ";
    cout<<char('A'+n-1);
    cout<<endl;
  for(int i=1;i<=n-1;i++) {
    for(int j=n-1;j>i;j--)
    cout<<" ";
    for(int k=i;k>=0;k--)
    cout<<char('A'+n-k-1);
    for(int l=n-2;l>=n-i-1;l--)
    cout<<char('A'+l);
        cout<<endl;
  }
}

问题 I: 数值计算

题目描述

小明同学不仅数学学得超棒,而且计算机语言编程能力也超强。这一天,数学王老师给同学们留了这样一道题:在任意的一段四位自然数区间内,找出符合以下特点的四位自然数 ABCD:
(1)这个四位自然数是素数;
(2)它的前两位数 AB 是完全平方数;
(3)它的后两位数 CD 也是完全平方数。
现给出任意自然数 M ~N 的区间,要求:求出所有满足上述条件的数值,并统计出它们的个数。小明同学很快给出了答案,在座的同学们,你们是如何计算的呢?

输入

只有一行,包含用1个空格隔开的两个四位自然数M和N(其中1000≤M

输出

共有若干行:
前若干行:每行一个数值为所有满足上述条件的数值;
最后一行:只有一个数值,为满足上述条件的数值的个数。

样例输入
复制样例数据 1000 3000

样例输出
1601
1609
2549
3

这题数据比较水,直接打表就行了 跟凯哥学的hhhh 代码: 注意自己写一个判断素数的函数和判断完全平方数的函数

#include//打表代码
using namespace std;
int isp(int n)
{
    for(int i=2;i*i<=n;i++)
    if(n%i==0)
    return 0;
    return 1;
}
int check(int n)
{
    double a=sqrt(n);
    int b=sqrt(n);
    if(a==b)
    return 1;
    else
    return 0;
}

int main() {
  freopen("ans.txt","w",stdout);
  for(int i=1000;i<=9999;i++) {
    if(isp(i)) {
      if(check(i%100)&&check(i/100))
      cout<<i<<",";
    }
  }
}
#include//提交的代码
using namespace std;
int a[10000];
int main() {
  /*1601,1609,2549,4909,6449,6481,8101,*/
  a[1601]=1;
  a[1609]=1;
  a[2549]=1;
  a[4909]=1;
  a[6449]=1;
  a[6481]=1;
  a[8101]=1;
  int n,m;
  cin>>n>>m;
  int sum=0;
  for(int i=n;i<=m;i++) {
    if(a[i]) {
    cout<<i<<endl;
    sum++;
    }
  }
  cout<<sum;
}
这里说一下上面那个自己写的check函数 一个类型是int 一个类型是double 如果是完全平方数的话那这两个值就相等,return 1; 如果不是的话return 0;

问题 J: 字符串VII

题目描述

从键盘输入任意的一个字符串A , 其 长 度 L 不 小 于 6 , 同 时 再 输 入 一 个 整 数 N ( 其 中 : N < L ) 作 为 插 入 点 , 以 及 任 意 的 一 个 字 符 串 B ,其长度L不小于6,同时再输入一个整数N(其中:N<L)作为插入点,以及任意的一个字符串B L6NN<LB,其长度为L1(其中:L1 (1)计算字符串A 的 长 度 L ; ( 2 ) 查 找 字 符 串 A 的长度L; (2)查找字符串A L2A中,从左到右第一个出现字母a的位置;
(3)在N点处,插入字符串B$后,将得到一个新字符串,请计算并输出最后的字符串。

输入

共有三行:
第一行:长度为 L 的字符串 A ( L ≥ 6 ) ; 第 二 行 : 一 个 整 数 N , 作 为 字 串 的 插 入 点 ( N < L ) ; 第 三 行 : 长 度 为 L 1 的 字 符 串 B ( L≥6); 第二行:一个整数 N,作为字串的插入点(N<L); 第三行:长度为 L1 的字符串 B (L6)NN<L;L1B(其中:L1

输出

共有三行:
第一行:字符串 A 的 长 度 L ; 第 二 行 : A 的长度 L; 第二行:A L;A中第一个出现字母 a 的位置;
第三行:在 N 点处,插入字符串 B$后得到的新字符串。
【要求】每行的输出数据从第一列输出

样例输入
复制样例数据 ABCDabcdaxy
4
hello

样例输出
11
5
ABChelloDabcdaxy

这题用到了前几天学的那个函数,虽然说没有多大的用处,但是怎么说也是活学活用了2333 这题直接再定义一个string,然后从该插入的地方之前先加上之前的,然后插入就从要插入的字符串第0项全部塞到string中,最后再从n-1开始把字符串A剩下的给添加上去就行了。

 #include
using namespace std;
int main() {
  string a;
  string b;
  string c;
  int d;
  cin>>a>>d>>c;
  int l=a.size();
  int ll=a.find('a')+1;
  for(int i=0;i<d-1;i++)
    b+=a[i];
  for(int i=0;i<c.size();i++)
    b+=c[i];
  for(int i=d-1;i<l;i++)
    b+=a[i];
    cout<<l<<endl<<ll<<endl<<b;
}

问题 K: 身高排队

题目描述

实验小学为了强健学生的身体,每天课间都要组织学生在户外学做广播体操。
这一天,五年级三班的所有同学在老师的指引下将队形排成了 M 行 N 列。
现已知所有同学的身高,数值为整数,单位:厘米。要求在所有同学中:
(1)挑选出每列身高最高的同学作为此列的小队长为同学们带操;
(2)将所有同学按身高从高到低的顺序进行排队;
(3)求出所有同学们的平均身高(要求:四舍五入保留整数);
(4)统计出不小于平均身高的学生人数。
请同学们用计算机编程的方法来解决以上问题。

输入

共有M+1行:
第一行有:用1个空格隔开的两个整数M、N,分别代表学生的行数和列数(其中1≤M≤10,1≤N≤10);
后M行有:每一行对应的是N列数据,表示所有学生的身高尺寸,数值为整数,单位:厘米(其中:140厘米≤身高≤170厘米,不需判断此条件),数据之间空1格。

输出

文件中共有M+3行:
前M行:每行一个数据为各列中身高最高的同学的高度(要求:各列按从左到右的顺序);
第M+1行:为所有同学按身高从高到低的顺序排队的高度(要求数据之间有1个空格);
第M+2行:只有一个数据为所有同学的平均身高(要求:四舍五入,保留整数);
第M+3行:只有一个数据,为不小于平均身高的学生人数。

样例输入
复制样例数据 3 4
141 161 156 167
170 163 168 157
162 145 153 163

样例输出
170
163
168
167
170 168 167 163 163 162 161 157 156 153 145 141
159

这题真实被恶心到了 虽然不是很难,但是东西太多了,这里也用到了大前天比赛刚学到的round函数,这些函数真好用啊!在找一列中最大的时候有个小细节,就是把矩阵给转过来比较,注意这一点就行了 代码:

#include
using namespace std;
int a[100][100];
int b[10000];
int maxn=-9999;
int main() {
  ios::sync_with_stdio(false);
  cin.tie(false);
  cout.tie(false);
  int m,n;
  cin>>m>>n;
  int k=0;
  int sum=0;
  for(int i=0;i<m;i++)
    for(int j=0;j<n;j++) {
      cin>>a[i][j];
      b[k]=a[i][j];
      k++;
      sum+=a[i][j];
    }
  for(int i=0;i<n;i++) {
    maxn=-9999999;
    for(int j=0;j<m;j++) {
      if(a[j][i]>maxn)
      maxn=a[j][i];
    }
    cout<<maxn<<endl;
  }
  sort(b,b+k,greater<int>());
  for(int i=0;i<k;i++)
  cout<<b[i]<<" ";
  cout<<endl;
  double ans=round(1.0*sum/(n*m));
  cout<<ans;
  int sum1=0;
  for(int i=0;i<k;i++) {
    if(b[i]>=ans)
    sum1++;
  }
  cout<<endl;
  cout<<sum1;
}

问题 L: 阶乘后K位

题目描述

n的阶乘定义为n!=123*…*n,如3!=6,5!=120,特殊的0!=1.n!通常最后会有很多0,如5!=120,最后有一个0,现在给定你一个正整数n,请你编程求n!去除末尾的0后(注意是尾部所有的0,意味着从右往左看第一个非零数字右边所有的零都去掉),最后的k位是多少。

输入

只有一行:包含两个正整数n和k,两数间用一个空格分隔。(1<=n<=1400000,1<=k<=10)

输出

仅一行:包含一个k位数.如果n!去掉尾部的0后不止k位,则输出最后k位,如果不足k位,则高位补零,补足k位后输出。

样例输入
复制样例数据 7 2

样例输出
04

提示

7!为5040,去除末尾的0后变为504,最后两位为04,故输出为04。

这里在处理的时候看了mhr大佬的博客问我为什么老是看他博客?因为我菜呗
第一次提交的时候我忘记高位补零了,wa了以后不知道为什么,然后大佬让我试试7 10 发现根本没有输出!后来一看才发现原来我的string根本没有那么多位 !在前面加了高位补0的操作才ac的 注意一下ans%一百亿 (因为k最大位数才是10 所以再大的数只要除以10位数把后面的0抹去就行了) 代码:?

#include
using namespace std;
int main() {
  int n,k;
  cin>>n>>k;
  long long int ans=1;
  for(int i=1;i<=n;i++) {
    ans*=i;
    while(ans%10==0)
    ans/=10;
    ans%=1000000000;
  }
  stringstream s;
  s<<ans;
  string ss;
  s>>ss;
  for(int i=ss.size();i<k;i++)
  ss='0'+ss;
  for(int i=ss.size()-k;i<ss.size();i++)
  cout<<ss[i];
}

问题 M: 寻找指定的特殊素数

**题目描述

有一种特殊素数,它本身是一个素数,从右边开始逐位去掉,剩下的数也总是素数。例如7331,是一个素数,去掉尾部的1,剩下数字733,也是一个素数;再去掉尾部的3,剩下73,还是一个素数,继续去掉尾部的3,剩下7,仍然是一个素数,我们就把7331叫做长度为4的特殊素数。如果长度为n的特殊素数有若干个,我们将它们从小到大排列,最小的我们称它的位置为1,次小的位置为2,第三小的位置为3,以此类推,编写程序寻找长度为n,指定位置为m的特殊素数,如果n位特殊素数共有k个,但m>k,我们就说指定位置m上没有特殊素数,则输出“Error!”(不包括引号)。注:数字1不被看作一个素数。

输入

只有一行:包含两个正整数n和m,两数间用一个空格分隔。(1<=n<=8,1<=m<=100)

输出

仅一行:如果指定长度和位置的素数存在就输出这个素数,否则输出“Error!”(不包括引号)。

样例输入
复制样例数据 4 6

样例输出
3119

提示

长度为 4 的特殊素数从小到大依次为 2333 2339 2393 2399 2939 3119 3137…,可以看出位置为 6 的素数为 3119。

没写 原因(菜)233333

这就是本次比赛的全部内容了!这个题。。我尽量补了把 多谢阅读!

你可能感兴趣的:(周赛/中石油题解)