0
点赞
收藏
分享

微信扫一扫

湖南中医药大学2017年集训队第二场选拔赛

是波波呀 2022-11-15 阅读 168


Problem A: 最小公倍数


Time Limit: 1 Sec   Memory Limit: 128 MB

Submit: 3201  

Solved: 785

[

​​Submit​​][

​​Status​​][

​​Web Board​​]


Description


求两个数的最小公倍数LCM(Least Common Multiple)


Input


每行包含两个数a,b

当a和b都等于0时表示输入结束,这组数据不用输出


Output


每行包含一个正整数:a和b的最小公倍数


Sample Input


4 6


3 5


0 0


Sample Output


12


15


【分析】


辗转相除法


【代码】


#include<stdio.h>
int main()
{
long long a,b;
long long t;
long long x,y;
while(~scanf("%lld%lld",&a,&b))
{
if(a==0&&b==0) break;
x=a;
y=b;
while(b!=0)
{
t=a%b;
a=b;
b=t;
}
long long m=x*y/a;
printf("%lld\n",m);
}
}


Problem B: 又是比智力


Time Limit: 1 Sec   Memory Limit: 128 MB

Submit: 1230  

Solved: 219

[

​​Submit​​][

​​Status​​][

​​Web Board​​]


Description



松哥上了数学课之后,觉得自己智力实在有所不足,所以他决定找人辩论,以提高自己的智力,已知松哥目前的智力是m,他决定和n个人辩论,如果他对手的智力低于他,松哥的智力能够提升2,否则只能提升1,假设松哥能够取得所有的胜利,请问他完成n场辩论后能够得到的最高智力是多少?



Input



多组测试数据.



每组测试数据的第一行包含两个正整数m,n.(m<=100,n<=10^5)



第二行为n个不大于100的整数,代表与他辩论人的智力.



Output



对于每组测试数据,他完成n场辩论后,能取得的最大的智力.



Sample Input



91 5



88 90 92 94 98



Sample Output



101



【分析】



基础贪心,先对所有人的智商进行排序,排序后从最低的开始比赛,因为显然先提升自己的智商对自己更有利,当剩下的人都比自己智商高的时候,就考虑跟智商最高的人去比一场赛使自己的智商+1然后继续跟剩下的人里智商最低的比....加个小优化,数据里说其他人的智商最多只有100,所以当自己的智商超过100的时候剩下的人就不需要比了肯定是能获胜的...当然这个优化没什么意义...



【代码】



#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
int a[100000];
using namespace std;
int main()
{
int m,n;
while(~scanf("%d %d",&m,&n))
{
int i;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
sort(a,a+n);
int x=0;
for(i=0;i<n;i++)
{
if(m>a[i])
m+=2;
else
{
m+=1;
a[n-1]=0;
sort(a,a+n);
}
if(m>100)
{
x=1;
break;
}
}
if(x==1)
m+=(n-1-i)*2;
printf("%d\n",m);
}
return 0;
}







Problem C: 01字串


Time Limit: 1 Sec   Memory Limit: 128 MB

Submit: 88  

Solved: 71

[

​​Submit​​][

​​Status​​][

​​Web Board​​]


Description



对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能。它们的前几个是: 00000 00001 00010 00011 00100 请按从小到大的顺序输出这32种01串。



Input



 本试题没有输入。



Output



 输出32行,按从小到大的顺序每行一个长度为5的01串。



Sample Input






Sample Output



00000



00001



00010



00011



< 以下部分省略>



【分析】



一种解法是打表...然而这种不存在超时情况的题目没有必要打表....



乍一眼就看得出来这个其实只是二进制.....所以从小到大输出也就是从0的二进制输出到(2^5)-1=31的二进制



【代码】



#include <iostream>    
#include <cstdio>
#include <math.h>
using namespace std;

void write(int x)
{
for(int i=4;i>=0;i--)
{
if(x&(1<<i))
printf("1");
else
printf("0");
}
puts("");
}
int main()
{
for(int i=0;i<=31;i++)
write(i);
return 0;
}


Problem D: 2n皇后问题


Time Limit: 1 Sec   Memory Limit: 128 MB

Submit: 12  

Solved: 9

[

​​Submit​​][

​​Status​​][

​​Web Board​​]


Description



给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。



Input



 输入的第一行为一个整数n,表示棋盘的大小。接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。



Output



 输出一个整数,表示总共有多少种放法。



Sample Input



4



1 1 1 1



1 1 1 1



1 1 1 1



1 1 1 1



4



1 0 1 1



1 1 1 1



1 1 1 1



1 1 1 1



Sample Output



20



【分析】



本场比赛最难的题了吧应该算是.....基础dfs...



做两次n皇后问题就可以了,两层dfs,dfs写法很多种,无所谓怎么写,数据n<=8所以直接爆搜不会超时的...



本人比较懒所以这个代码在我心里是属于第二级别的...个人认为最好的代码风格应该是分成两个dfs写



dfs先搜黑皇后摆放,放完之后dfs再搜一次白皇后摆放,因为黑白皇后互相之间没有影响,唯一的影响只有点是否占领,这道题里棋盘中是有位置不能放皇后的,所以需要



//1表示当前位能放皇后



//2表示当前位放白(黑)皇后



//3表示当前位放黑(白)皇后



放置黑白皇后的先后对答案没有影响...



【代码】



#include <stdio.h>
#include <string.h>
int a[20][20];
int sum;
int n;
int judge(int i,int j,int k)
{
for(int r=0;r<n;r++)
if(a[r][j]==k)
return false;
for(int c=0;c<n;c++)
if(a[i][c]==k)
return false;
for(int r=i-1,c=j-1;r>=0&&c>=0;r--,c--)
if(a[r][c]==k)
return false;
for(int r=i+1,c=j+1;r<n&&c<n;r++,c++)
if(a[r][c]==k)
return false;
for(int r=i-1,c=j+1;r>=0&&c<n;r--,c++)
if(a[r][c]==k)
return false;
for(int r=i+1,c=j-1;r<n&&c>=0;r++,c--)
if(a[r][c]==k)
return false;
return true;
}
void find(int i,int flag)
{
if(i>=n)
{
if(!flag) {sum++;flag=1;return;}
flag=0;
i=0;
}
if(flag)
{
for(int j=0;j<n;j++)
if(judge(i,j,2)&&a[i][j]==1)
{
a[i][j]=2;
find(i+1,flag);
a[i][j]=1;
}
}
else
{
for(int j=0;j<n;j++)
if(judge(i,j,3)&&a[i][j]==1)
{
a[i][j]=3;
find(i+1,flag);
a[i][j]=1;
}
}
}
int main()
{
while (~scanf("%d",&n))
{
memset(a,0,sizeof(a));
sum=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&a[i][j]);
find(0,1);
printf("%d\n",sum);
}
return 0;
}


Problem E: 勇者斗恶龙


Time Limit: 1 Sec   Memory Limit: 128 MB

Submit: 1032  

Solved: 394

[

​​Submit​​][

​​Status​​][

​​Web Board​​]


Description



你的王国里有一条n个头的恶龙,你希望雇一些骑士把它杀死(即砍掉所有头)。村里有m个骑士可以雇佣,一个能力值为x的骑士可以砍掉恶龙一个直径不超过x的头,且需要支付x个金币。如何雇佣骑士才能砍掉恶龙的所有头,且需要支付的金币最少?注意,一个骑士只能砍掉一个头(且不能被雇佣两次)。



Input



输入包含多组数据。每组数据的第一行为正整数n和m(1<=n,m<=20 000);以下n行每行为一个整数,即恶龙每个头的直径;以下m行每行一个整数,即每个骑士的能力。

输入结束标志为n=m=0。



Output



对于每组数据,输出最少花费。如果无解,输出“Loowater is doomed!”。



Sample Input



2 3



5



4



7



8



4



2 1



5



5



1 0



0 0



Sample Output



11



Loowater is doomed!



【分析】



也算是基础贪心吧,首先对龙和骑士的能力分别进行排序,然后两个指针i表示当前第i个头,指针j表示当前第j个骑士,如果当前骑士可以杀掉当前头,就用当前骑士杀掉这个头,如果不能,则j++找下一个骑士,如果骑士用完了头还没杀完就是Loowater is doomed!



这里因为数据较小,所以我用直接标记记录骑士的能力值的方法,每次判断是否存在能力和第i个头能力相同的骑士,如果没有,则给第i个头的能力值+1,直到找到能杀掉这个头的骑士或者找不到骑士则Loowater



这个方法的速度好像是比排序来的快一点点的...但是对于这种数据这种优化依然没有什么意义....



【代码】



#include <stdio.h>
int n,m;
int a[30000]={0};
int b[30000]={0};
int main()
{
while (~scanf("%d%d",&n,&m)&&(n||m))
{
int i,max=0,sum=0,rider,t=0;
for (i=1;i<=n;i++) scanf("%d",&a[i]);
for (i=1;i<=m;i++)
{
scanf("%d",&rider);
b[rider]++;
if (rider>max) max=rider;
}
for (i=1;i<=n;i++)
{
while (b[a[i]]==0 && a[i]<=max) {a[i]++;}
if (a[i]>max)
{
t=1;
break;
}
b[a[i]]--;
sum+=a[i];
}
if (t==1)
printf("Loowater is doomed!\n");
else
printf("%d\n",sum);
for (i=1;i<=max;i++) b[i]=0;
}
}


Problem F: 工程


Time Limit: 1 Sec   Memory Limit: 128 MB

Submit: 108  

Solved: 70

[

​​Submit​​][

​​Status​​][

​​Web Board​​]


Description



某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。



Input



本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。

 


 



Output



对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.



Sample Input



3 3



0 1 1



0 2 3



1 2 1



0 2



3 1



0 1 1



1 2



Sample Output



2



-1



【分析】



标准的最短路模板...不过标准的最短路也没有什么模板这种说法...翻模板还不如自己直接敲快的多....



bfs或者弗洛伊德算法都可以反正数据依然很小....



//因为我个人很少用弗洛伊德算法...所以刚好有这个机会稍微练习一下这个算法就用了...



【代码】



#include <stdio.h>
#include <algorithm>
#define inf 0x3f3f3f3f
int f[250][250];
int n,m;
int main()
{
int a,b,x,s,t,ans;
while(~scanf("%d %d",&n,&m))
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
f[i][j]=(i==j?0:inf);
while(m--)
{
scanf("%d %d %d",&a,&b,&x);
if(x<f[a][b])
f[a][b]=f[b][a]=x;
}
scanf("%d%d",&s,&t);
for(int t = 0;t < n;t++)
for(int i = 0;i < n;i++)
for(int j = 0;j < n;j++)
if(f[i][j] > f[i][t] + f[t][j])
f[i][j] = f[i][t] + f[t][j];
printf("%d\n",f[s][t]==inf?-1:f[s][t]);
}
return 0;
}





Problem G: 矩形A + B


Time Limit: 1 Sec   Memory Limit: 128 MB

Submit: 196  

Solved: 163

[

​​Submit​​][

​​Status​​][

​​Web Board​​]


Description


给你一个高为n ,宽为m列的网格,计算出这个网格中有多少个矩形,下图为高为2,宽为4的网格.

湖南中医药大学2017年集训队第二场选拔赛_数据



Input



第一行输入一个t, 表示有t组数据,然后每行输入n,m,分别表示网格的高和宽 ( n < 100 , m < 100).



Output



每行输出网格中有多少个矩形.



Sample Input



2



1 2



2 4



Sample Output



3



30



【分析】


数据依然很小....找找规律就好了...当然如果真的...找不到规律...实在不行就打表吧.....反正数据也小...但是还是那句话,不存在超时的情况,打表就没有意义...


所以不如算一算啊,数一数啊,找找规律啊~什么的最有爱了


如果只看一行的话,长度为1的有m个,长度为2的有m-1个……,长度为m的有1个。


那么每一行就有:1+2+3+……+m个=m * (m + 1) / 2。


然后再竖过来看每一列也是一样的:1+2+3+……+n个=n * (n + 1) / 2。


所以横竖两种可能乘一下就好了...答案就是(1+m)*m/2*(1+n)*n/2


//这件事告诉我们小学奥数学的好是多么的重要....幸好之前之江学院的比赛复习了一大波小学奥数题....


【代码】


#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
int main()
{
int t;scanf("%d",&t);
for (int p=0;p<t;p++)
{
int n,m,sum1,sum2;
scanf("%d %d",&n,&m);
sum1=(1+n)*n/2;
sum2=(1+m)*m/2;
printf("%d\n",sum1*sum2);
}
return 0;
}


Problem H: 字母图形


Time Limit: 1 Sec   Memory Limit: 128 MB

Submit: 81  

Solved: 41

[

​​Submit​​][

​​Status​​][

​​Web Board​​]


Description



问题描述 利用字母可以组成一些美丽的图形,

下面给出了一个例子:

ABCDEFG

BABCDEF

CBABCDE

DCBABCD

EDCBABC

这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。



Input



  输入一行,包含两个整数n和m,分别表示你要输出的图形的行数的列数。 数据规模与约定 1 < = n, m < = 26。



Output



 输出n行,每个m个字符,为你的图形。



Sample Input



5 7



Sample Output



ABCDEFG



BABCDEF



CBABCDE



DCBABCD



EDCBABC



【分析】



找规律输出的一道题...没什么好说的



【代码】



#include <stdio.h>
int main()
{
int n,m;
while (~scanf("%d%d",&n,&m))
{
for (int i=0;i<n;i++)
{
int j=0;
for (char a='A'+i;a>'A'&&j<m;a--)
{
printf("%c",a);
j++;
}
for (char a='A';a<='Z'&&j<m;a++)
{
printf("%c",a);
j++;
}
puts("");
}
}
return 0;
}



举报

相关推荐

0 条评论