陕西科技大学暑期集训热身赛(二)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43271086/article/details/95507070

1,三角形的面积

题目描述

我愿为自己加上private

在你的class中

只有你能调用

Lily的老师给他出了一个问题,给出三角形的三边长abc,lily要计算出这个三角形的面积,liy比较懒(周末要睡觉嘛),现在要向你求助。

输入

有多组测试数据,第一行输入一个整数T表示测试数据的组数。

接下来T组测试数据,每组测试数据占一行。该行包含三个整数a b c,为三角形的三边。

输出

对每组测试数据,输出一行。如果三条边能构成三角形,则输出三角形的面积并保留三位小数,否则输出“-1”。相邻两组测试数据输出之间有一个空行。

样例输入

2
1 2 3
3 4 5

样例输出

-1
 
6.000

代码展示

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int main(int argc, char const *argv[]) {
  int T;
  cin>>T;
  while(T--){
    double a,b,c;
    //应flag表示这组数据是否可以用
    int flag=0;
    double sum=0;
    cin>>a>>b>>c;
    //条件判断,可能我的条件写的有点复杂
    if(a+b>c&&a+c>b&&b+c>a&&abs(a-b)<c&&abs(a-c)<b&&abs(b-c)<a){
      flag=1;
    }
    if(flag==1){
      //海伦公式
      double s=(a+b+c)/2;
      sum= sqrt(s*(s-a)*(s-b)*(s-c));
      //保留三位有效数字
      printf("%0.3f\n",sum);
    }
    else{
    cout<<-1<<endl;
   }
   //最后一组后面不做空行转换
   if(T){
   cout<<endl;
 }
  }
  return 0;
}

2.小辉辉玩积木

这道题我WA了一次,显示错误是时间超限,所以我先用数组进行打表,最后过了。

题目描述

渣渣辉有个儿子叫小辉辉,他非常喜欢数论。

有一天,小辉辉在玩积木时,对渣渣辉提出了一个问题:

在2×n的一个长方形方格中用一个1×2的积木铺满方格输入n 输出铺放方案的总数. 

例如n=3时为2×3方格,积木的铺放方案有三种如下图: 

输入

输入数据由多行组成,每行包含一个整数n表示该测试实例的长方形方格的规格是2×n (0<n<=50)。

输出

对于每个测试实例,请输出铺放方案的总数,每个实例的输出占一行。

样例输入

1
3
2

样例输出

1
3
2

代码展示

#include <iostream>
using namespace std;
 
int main() {
    int  n;
    //先利用数组将结果存起来,因为只有50组a。
    long long int ans[52]={0};
    ans[1] = 1;ans[2] = 2;
    for(int i = 3; i < 52; i ++) {
        ans[i] = ans[i - 1] + ans[i - 2];
    }
    while(scanf("%d",&n)!=EOF) {
        cout << ans[n] << endl;
    }
    return 0;
}

3.括号匹配

题目描述

给定一串由括号组成的字符串,请你判断这些括号是否一一匹配。

一个左括号“(”匹配一个右括号")”。

类似:“()”、"(())","()()",“(()())”等都是匹配的。

而“(()”,"())"等都是不匹配的。

给定的字符串只包含左右括号和空格。类似于“()(    )( (  )          )”的输入是合法的,且这个字符串是匹配的。

输入

输入包含多组输入数据,需要处理到文件末尾。

每个测试样例占一行,只包含左右括号符号和空格。符号和空格的形成的字符串的最大长度不超过1000。

输出

对于每一个输入样例

如果括号完全匹配成功,输出"Yes"。

否则输出"No"。

样例输入

()()()()(()()()())
(          )
(   () )
(())))))))))()
)(

样例输出

Yes
Yes
Yes
No
No

解题原理:利用栈的思想,将左括号存入栈中,然后将右括号进行匹配,匹配成功则将左括号从栈中弹出即可,遇到空格直接进行continue就可以了

代码展示

#include<iostream>
#include<cstring>
#include<stack>
#include<cstdio>
using namespace std;
int main(int argc, char const *argv[]) {
  string a;
  while(getline(cin,a)){
    stack<char>s;
    int flag=0;
    for(int i=0;i<a.length();i++){
      if(a[i]=='('){//入栈
        s.push(a[i]);
      }
      else if(a[i]==' '){//继续进行,不要管他
        continue;
      }
      else if(a[i]==')'&&!s.empty()){//因为栈不为空时就存取的是左括号,所以直接用非空进行判断
          s.pop();
        }
        //在这里,如果右括号的个数比左括号多的时候,我们直接返回即可。
      else{
        flag=1;
         break;
    }
  }
  //所以判断就是,要不是左括号多,就是右括号多的情况
    if(!s.empty()||flag==1){
      cout<<"No"<<endl;
    }
    else{
      cout<<"Yes"<<endl;
    }
  }
  return 0;
}

4,礼物

题目描述

四月一日快到了,Vayko想了个愚人的好办法——送礼物。嘿嘿,不要想的太好,这礼物可没那么简单,Vayko为了愚人,准备了一堆盒子,其中有一个盒子里面装了礼物。盒子里面可以再放零个或者多个盒子。假设放礼物的盒子里不再放其他盒子。 

用()表示一个盒子,B表示礼物,Vayko想让你帮她算出愚人指数,即最少需要拆多少个盒子才能拿到礼物。 

输入

本题目包含多组测试,请处理到文件结束。 
每组测试包含一个长度不大于1000只包含'('')'和'B'三种字符的字符串,代表Vayko设计的礼物透视图。 
你可以假设,每个透视图画的都是合法的。 

输出

对于每组测试,请在一行里面输出愚人指数。

样例输入

((((B)()))())
(B)

样例输出

4
1

解题思路:还是利用栈的思想,左括号进行存栈,右括号进行匹配,然后遇到礼物的时候进行截至,然后输出栈中还有多少个左括号。

#include <iostream>
#include<stack>
#include<cstring>
using namespace std;
int main(int argc, char const *argv[]) {
  char a[1001];
  stack<char>s;
  while(scanf("%s",&a)==1){
    int length=strlen(a);
    for(int i=0;i<length;i++){
      if(a[i]=='(') s.push(a[i]);
      if(a[i]==')'&&s.top()=='(') s.pop();
      //找到礼物的时候,就进行跳出。
      if(a[i]=='B'){
        cout<<s.size()<<endl;
        break;
      }
    }
    //对栈进行清空操作,方便下一组数据进来不受影响
    while(!s.empty()){
      s.pop();
    }
  }
  return 0;
}

5,单身狗的寻觅

题目描述

你是个单身狗吗?那就来相亲吧!

西安有一个神奇的地方,叫做“SUST_ACM 婚姻介绍所”。

里面有很多需要相亲的程序猿和程序媛。

每个人等待相亲的人都有一个编号(有可能重复),其中程序猿为奇数,程序媛为偶数。

现在他们正排成一排等待相亲。

每个人都只能和相邻的两个人配对,当然绝不允许同性配对。

老大想让介绍所的撮合对数最大化,你告诉老大最多可以匹配多少对吗?

输入

输入包含多组测试数据。

对于每组测试样例:

第一行输入为一个整数 N (1 ≤ N ≤ 108)。

第二行输入 N 个正整数(0 < ID ≤ 10000)。

输出

输出可以匹配的最大对数。

样例输入

6
1 2 3 4 5 5

样例输出

2

做题思路:将数据一个一个往里面读,这样就从后面往前判断,然后前面的数据进行标记,如果未标记则与现在的数据进行判断,如果标记了,则现在的数据就等待下一个数据进行匹配

#include<iostream>
#include<cstring>
using namespace std;
int main(int argc, char const *argv[]) {
  int N;
  while(cin>>N){
    int a=0,b,c;
    int count=0;
    //首先你得读一个数进来。
  cin >> b;
  //总数减去一
  N -=1;
 while(N--){
   cin>>c;
   //利用a对当前数据进行标记,如果匹配成功则a=1;,否则保持不变
 if((b&1)+(c&1)==1&&a==0){
   count++;
   a=1;
 }
 else{
   a=0;
 }
 //将当前的数赋值给b,然后进行下一个数的读入
 b=c;
}
cout<<count<<endl;
}
  return 0;
}

6,勇敢者的游戏

题目描述

各位勇敢者要玩的第一个游戏是什么呢?很简单,它是这样定义的: 
1、  本游戏是一个二人游戏; 
2、  有一堆石子一共有n个; 
3、  两人轮流进行; 
4、  每走一步可以取走1…m个石子; 
5、  最先取光石子的一方为胜; 

如果游戏的双方使用的都是最优策略,请输出哪个人能赢。

输入

输入数据首先包含一个正整数C(C<=100),表示有C组测试数据。 
每组测试数据占一行,包含两个整数n和m(1<=nm<=10000),n和m的含义见题目描述。 

输出

如果先走的人能赢,请输出“first”,否则请输出“second”,每个实例的输出占一行。

样例输入

2
23 2
4 3

样例输出

first
second

解题思路:这道题就是简单的博弈,因为每次都是最优策略,所以都取最多的石头,则只要是第一个人取的最多的石头进行加一操作就是另外一个人赢了,所有总数是(m+1)的倍数时是第二个人赢。

#include<iostream>
using namespace std;
int main(int argc, char const *argv[]) {
 int C;
 cin>>C;
 int n,m;
 while(C--){
   cin>>n>>m;
   if(n%(m+1)==0){
     cout<<"second"<<endl;
   }
   else{
     cout<<"first"<<endl;
   }
 }
  return 0;
}

7.赛马(经典)

题目描述

古有田忌赛马戏齐王,今有悠悠赛马虐渣渣。悠悠和他的小老弟渣渣每人有n匹马,每匹马都有一个评分,分数越高速度越快。现在渣渣不甘于当小老弟,随着赛马曲的想起,渣渣决定挑战悠悠,规则同田忌赛马。每胜一局得1分,每负一局减一分,赵神做裁判,悠悠为了捍卫自己的王者地位,决定出老千,问了赵神关于渣渣的赛马顺序,请问悠悠最高能得多少分。

输入

文件有多组测试样例,遇0为止。

首行一个整数n,n<=1000;

第2行n个整数表示悠悠每匹马的分数。

第3行n个整数表示渣渣每匹马的分数。0<=分数<500;

输出

输出悠悠最高分。

样例输入

3
192 173 71
195 177 74
2
10 10
10 10
2
220 219
222 218
0

样例输出

1
0
0

我也是wa了五次这道题才过的,还是那句话,最优解才是最好的。我们想一下当时的田忌赛马的情形,田忌用的下等马对齐王的上等马,用上等马对齐王的中等马,用中等马对齐王的下等马。我们也是这样的思路,如果悠悠的下等马比渣渣的下等马厉害,那就我们直接赢,如果没有他的厉害,我们就把他当作炮灰直接与渣渣的上等马进行比较,这样我们的上等马就有了优势了,如果是相等的情况,你是不是认为这是最好的结果,其实不然,相等的时候相当于赢一次和输一次,其实这是下下签,相等的时候,我们就用最慢的搞他最快的马,这样,我们最快的马是不是就有更多机会了,你说是吧。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int main(int argc, char const *argv[]) {
  int N;
  while(cin>>N){
    while(N==0){
      return 0;
    }
    int a[N];//悠悠马
    int b[N];//渣渣马
    for(int i=0;i<N;i++){
      cin>>a[i];
    }
    for(int j=0;j<N;j++){
      cin>>b[j];
    }
    int num=0;
    sort(a,a+N);//由慢到快
    sort(b,b+N);
    //确定快马和慢马的位置
    int hlen1=N-1,llen1=0;
    int hlen2=N-1,llen2=0;
    while(hlen1>=llen1){
      //我们最慢的比他的最慢的快,我们赢
      if(a[llen1]>b[llen2]){
        num++;
        llen1++;
        llen2++;
      }
      //要不然就成为炮灰,打他最快的马
      else if(a[llen1]<b[llen2]){
        llen1++;
        hlen2--;
        num--;
      }
      else{
        //最快的比他快
        if(a[hlen1]>b[hlen2]){
          num++;
          hlen1--;
          hlen2--;
        }
        //没有他快的时候就用慢打快,个人理解这里包含相等的情况,所以没有括号
        else {
          if(a[llen1]<b[hlen2])
          num--;
          llen1++;
          hlen2--;
      }
     }
    }
    cout<<num<<endl;
  }
  return 0;
}

8,渣渣辉别墅前的水潭

题目描述

渣渣辉有一栋超级大的别墅。

唯一不好的是别墅前面有一个很大的庭院,那里总是积水。

渣渣辉想知道庭前有多少个多少片水滩。

水用W(大写)表示,两个W在上下左右,左上右上,左下右下任何一个方向连在一起视为同一片水滩。

输入

输入有多组测试样例;

对于每组测试样例:

第一行输入为两个正整数 n,m(0 <= n,m <= 100),表示庭院的长为n,宽为m。

接下来有n行输入为庭院的积水状况。‘W’代表水,‘.’代表空地。

输入n,m同时为0时结束。

输出

对于每一组测试样例,输出一个数字,为水滩个数。

样例输入

4 6
......
W.....
W.....
.W....
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
0 0

样例输出

1
3

解题思路:深搜。

#include<iostream>
#include<cstring>
using namespace std;
int vis[101][101];
char map[101][101];
int dic1[4]={1,0,-1,0};
int dic2[4]={1,0,-1,0};
int m,n;
void dfs(int x,int y){
  vis[x][y]=1;
  for(int i=0;i<4;i++){
    for(int j=0;j<4;j++){
      if(map[x+dic1[i]][y+dic2[j]]=='W'&&vis[x+dic1[i]][y+dic2[j]]==0&&x+dic1[i]>=0&&x+dic1[i]<m&&y+dic2[j]>=0&&y+dic2[j]<n)
      {
        dfs(x+dic1[i],y+dic2[j]);
      }
    }
  }
}
int main(int argc, char const *argv[]) {
 int ans=0;
 while(cin>>m>>n){
   memset(vis,0,sizeof(vis));
   if(m==0&&n==0){
     return 0;
   }
   for(int i=0;i<m;i++){
     for(int j=0;j<n;j++){
       cin>>map[i][j];
     }
   }
   for(int i=0;i<m;i++){
     for(int j=0;j<n;j++){
       if(map[i][j]=='W'&&vis[i][j]==0){
         ans++;
         dfs(i,j);
       }
     }
   }
   cout<<ans<<endl;
   ans=0;
 }
  return 0;
}

9,大整数相加

题目描述

来帮我算下A+B你肯定会算

输入

本题有多组测试数据

每行两个正整数 A B(0<AB<10^10000)

输出

每组数据在一行中输出 A+B的和 (保证A+B小于10^100000)

样例输入

1 2
11111111111111111111 22222222222222222222

样例输出

3
33333333333333333333

Java就三行代码:

import java.math.BigInteger;
import java.util.Scanner;
 
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()) {
            String s1 = sc.next(), s2 = sc.next();
            System.out.println(new BigInteger(s1).add(new BigInteger(s2)));
        }
    }
}

10,斐波那契求解。

题目描述

斐波那契数列的定义如下:

F(0) = 0

F(1) = 1

F(n) = F(n - 1) + F(n - 2) (n >= 2)

(1 1 2 3 5 8 13 21 34 55 89 144 233 377 ...)

给出n,求F(n),由于结果很大,输出F(n) % 1000000009的结果即可。

输入

输入1个数n(1 <= n <= 10^18)。

输出

输出F(n) % 1000000009的结果。

样例输入

11

样例输出

89

这道题如果用常规思路去做,肯定得wa,所以你需要简单学习一下矩阵运算和快速幂算法,学完之后你会发现这东西很神奇!!

#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const long long MOD=1000000009;
//矩阵结构体
typedef struct{
  ll a[2][2];
}mx;
//进行矩阵乘法,并且不停进行取余操作
mx juzhen_mul(mx x,mx y){
  mx res;
  memset(res.a,0,sizeof(res.a));
  for(int i=0;i<2;i++){
    for(int j=0;j<2;j++){
      for(int k=0;k<2;k++){
        res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j]%MOD)%MOD;
      }
    }
  }
  return res;
}
//快速幂算法
void fast_pow(ll n){
  mx c,res;
  c.a[0][0]=1;
  c.a[0][1]=1;
  c.a[1][0]=1;
  c.a[1][1]=0;
  memset(res.a,0,sizeof(res.a));
  for(int i=0;i<2;i++){
    res.a[i][i]=1;
  }
  while(n){
    //判断奇数还是偶数
    if(n&1)
    res=juzhen_mul(res,c);
    c=juzhen_mul(c,c);
    n=n/2;
  }
  cout<<res.a[0][1]<<endl;
}
int main(int argc, char const *arg1[]) {
 ll num;
  cin>>num;
  fast_pow(num);
  return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43271086/article/details/95507070