蓝桥杯第七届大学B组详解

文章讲述了编程中的7个数学题目,涉及找规律、动态规划、暴力枚举、最大公约数等技巧,强调理解题目的规律和总结方法在编程解题中的重要性。
摘要由CSDN通过智能技术生成

目录

1.煤球数量;

2.生日蜡烛;

3.凑算式

4.方格填数

5.四平方和

6.交换瓶子

7.最大比例


1.煤球数量

题目解析:可以根据·题目的意思,找到规律。

1     *-  1个

2    ***   3个

3   ******  6个

4 ********** 10个

不难发现 第一层的个数加上第二层的层数就是第二层的煤球数目。本质就是找规律数学。

#include <iostream>
#include<vector>
using namespace std;

int main()
{
    int n = 0, sum = 0;
    for(int i = 1; i <= 100; i++)
    {
          n += i;
          sum += n;
    }
    cout << sum << endl;
    return 0;
}

2.生日蜡烛

题目解析:直接枚举就行;

#include<iostream>
using namespace std;
int main()
{
	for (int i = 1;i <= 100; i++)
	{
		int sum = 0;
		for (int j = i; j <= 100; j++)
		{
			sum += j;
			if (sum == 236)
				cout << i << endl;
	 }
	}
	return 0;
}

3.凑算式

题目解析:是不是和三羊献瑞有点像,又可以使用next_premutation();

注意这个题目弄错了是1-9数字;md我就整整调试1个多小时,心态差点崩溃了,都开始怀疑自己了。

using namespace std;
#include<iostream>
#include<algorithm>

int ret = 0;
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};


bool check()
{
     int x = a[3] * 100 + a[4] * 10 + a[5];
     int y = a[6] * 100 + a[7] * 10 + a[8];

     if(((a[1] * y) + (a[2] * x)) % (a[2] * y) == 0 && a[0] + ((a[1] * y) + (a[2] * x)) / (a[2] * y) == 10)
     {
        return true;
     }
     else
     {
       return false;
     }
}

int main()
{
    do
    {
      if(check())
      {
         ret++;
      }
    }while(next_permutation(a, a + 9));

    cout << ret << endl;
    return 0;
}

4.方格填数

题目解析:动态规划类型题目,就是在方格中填数,如果这个方格没有被使用过并且方格相邻不重复就将数字填进去,填完就是一种方案数。累计方案数。

细节:初始化为-20,因为如果为填9就算相邻区分不出来。

#include <iostream>
#include<bits/stdc++.h>
using namespace std;

//方格矩阵,因为要使用到相邻的元素所以就会使用到就多创建行列
// -20   -20  -20-20
//    +--+--+--+
//    |  |  |  | -20
// +--+--+--+--+
// |  |  |  |  | -20
// +--+--+--+--+
// |  |  |  |    -20
// +--+--+--+
//-20  -20 -20 -20 -20
int a[4][5];
//判断是否被使用过
int vis[10];
int sum = 0;
int dx[4] = {-1, -1, -1, 0};
int dy[4] = {0, 1, -1, -1};

bool check(int x, int y, int num)
{
   for(int i = 0; i < 4; i++)
   {
      int xx = dx[i] + x;
      int yy = dy[i] + y;
      //边界检查
      if(xx < 3 && xx >= 0 && yy < 4 && yy >= 0)
      {
          //如果相邻的话那么相差一定为1;
          if(abs( a[xx][yy] - num ) == 1)
              return false;
      }
   }
   return true;
}


void dfs(int x, int y)
{
    //出口:第二行第三列
    if(x == 2 &&  y == 3)
    {
       sum++;
       return;
    }
    
    //开始填数
    for(int i = 0; i < 10; i++)
    {
        //判断没被使用过的方格并且不相临
        if(vis[i] == 0 && check(x, y, i))
        {
            vis[i] = 1;
            a[x][y] = i;
            //递归下一个方格,或者下一行
            if(y + 1 < 4)
               dfs(x, y + 1);
            else
               dfs(x + 1, 0);
            //回溯
            vis[i] = 0;
        }
    }
}

int main()
{
   //矩阵初始
    for(int i = 0; i < 4; i++)
   {
      for(int j = 0; j < 4; j++)
      {
         a[i][j] = -20;
      }
   }
   //从第0行第一列开始;
   dfs(0,1);
   cout << sum << endl;
   return 0;
}

5.四平方和

题目解析:可以想到暴力枚举的方法,复杂度为0(n^4)是非常恐怖的,那么就要想办法降低;就需要优化。

首先要知道 N=  a*a + b*b + c*c + d*d;

那么 a 一定不会超过 N / 4; b 一定不会超过 N / 3; c 一定不会超过 N / 2;

d 一定不会超过 N; 

其次我们可以先算 a 和 b,那么 N - a*a + b*b = c*c + d*d;

#include <iostream>
#include<map>
#include<cmath>
using namespace std;


int main()
{
   //输入
   int N; 
   cin >> N;
   map<int,int> exit;
   //c值存一下。
   for(int c = 0; c * c <= N / 2; c++)
   {
     for(int d = c; c*c + d*d <= N; d++)
     {
         if(exit.find(c * c + d * d) == exit.end())
            exit[c * c + d * d] = c;
     }
   }

   for(int a  = 0; a * a <= N / 4; a++)
   {
      for(int b = a; a*a + b*b <= N / 3; b++)
      {
         if(exit.find(N - a * a - b * b) != exit.end())
         {
            int c = exit[N - a * a - b * b];
            int d = (int)sqrt(N - a*a - b*b - c*c);
            cout << a << b << c << d << endl;
            //找到直接返回
            return 0;
         }
      }
   }

   return 0;
}

6.交换瓶子

题目解析:是不是会想到冒泡,但是你看看数据范围,那么就是肯定要优化;将当前元素与下标进行比较,如果相同直接跳过,不相同那么就要找到和下标相同的数据下标进行交换。

#include<iostream>

using namespace std;
int a[10001];
int N;
int sum = 0;

int pos(int x)
{
    for(int i = 1; i <= N; i++)
    {
       if(a[i] == x)
       {
          return i;
       }
    }
    return -1;
}

void Swap(int i, int j)
{
    int tmp = a[i];
    a[i] = a[j];
    a[j] = tmp;
}

int main()
{
   //数据处理;
   cin >> N;
   for(int i = 1; i <= N; i++)
   {
       cin >> a[i];
   }

   //进行查寻
   for(int i = 1; i <= N; i++)
   {
       if(a[i] == i)
          continue;
       else
       {
          //找到和下标不一样的数,和下标交换,不需要改变原来的值。
          Swap(pos(i), i);
          sum++;
       }
   }
   cout << sum << endl;
   return 0;
}

 7.最大比例

题目解析:本道题说到所有级别的奖金构成一个等比数列,先进行排序,将第一个数作为分母,分子分别都是后面的数,求取他们的最大公约数,再用两个数组将分子分母分别除以最大公约数,再存放起来。最后再对分子分母分别求差最小就会得到最终答案。

#include <iostream>
#include<algorithm>
using namespace std;

#define N 100
long long max = 1000000000;
long long x[N], a[N], b[N];


long long gcd(long long a, long long b)
{
     return b ? gcd(b, a % b) : a;
}

long long gcd_sub(long long a, long long b)
{
      if(b == 1) return a;
      if(b > a)  swap(a, b);
      return gcd_sub(b, a / b);
}

int main()
{
    //输入完成:
    int n;
    cin >> n;
    for(int i = 0; i < n; i++)
    {
       cin >> x[i];
    }
    
    //排序
    sort(x, x + n);

    long long dd;//求最大公约数
    int cnt = 0;
    for(int i = 1; i < n; i++)
    {
       if(x[i] != x[i-1]) //去除为1的情况
       {
          dd = gcd(x[i], x[0]);
          a[cnt] = x[i] / dd; //分子
          b[cnt] = x[0] / dd; //分母
          cnt++;
       }
    }

    long long up = a[0], down = b[0];
    for(int i = 1; i < cnt; i++)
    {
        up = gcd_sub(up, a[i]);
        down = gcd_sub(down, b[i]);
    }
     
     cout << up << "/" << down;
     return 0;
}

其实静下心来感受会觉得题目不难,就是要找到规律,总结方法,写代码注意细节,那么绝对可以取得高分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值