C++第12届蓝桥杯b组习题笔记

后三题,理解不到位。没写

 1. 空间

小蓝准备用 256MB 的内存空间开一个数组,数组的每个元素都是 32 位 二进制整数,如果不考虑程序占用的空间和维护内存需要的辅助空间,请问 256MB 的空间可以存储多少个 32 位二进制整数?

#include 
#include
using namespace std;
int main()
{
  // 请在此输入您的代码

  cout<<256*1024*1024/32*8;//1MB占用1024kb 占用1024*1024byte 再*8
  
  return 0;
}

2.卡片

好像和原题不一样,原题就是简单枚举

小蓝有 k 种卡片, 一个班有 n 位同学, 小蓝给每位同学发了两张卡片, 一 位同学的两张卡片可能是同一种, 也可能是不同种, 两张卡片没有顺序。没有 两位同学的卡片都是一样的。

给定 n, 请问小蓝的卡片至少有多少种?

C++第12届蓝桥杯b组习题笔记_第1张图片

规律:两种卡片 1能组合的有两种,2能组合的有一种 。

三种卡牌呢, 1能组合的有三种,2能组合的有两种,3能组合的有一种

#include 
#include
using namespace std;
int k;
int n;
int main()
{
  // 请在此输入您的代码
  scanf("%d",&n);
  
  int sum=0;
  int cnt=1;
  while(1)
  { 
    sum+=cnt;
    if(sum>=n)//分配的卡牌数超过同学数量
    {
      break;
    }
    cnt++;//表示到第几个数字
  }
  cout<

3. 直线

在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上, 那么这些点中任意两点确定的直线是同一条。

给定平面上 2 × 3 个整点(x,y)∣0≤x<2,0≤y<3,x∈Z,y∈Z(x,y)∣0≤x<2,0≤y<3,x∈Z,y∈Z​,即横坐标 是 0 到 1 (包含 0 和 1) 之间的整数、纵坐标是 0 到 2 (包含 0 和 2) 之间的整数 的点。这些点一共确定了 11 条不同的直线。

给定平面上 20×21 个整点 (x,y)∣0≤x<20,0≤y<21,x∈Z,y∈Z(x,y)∣0≤x<20,0≤y<21,x∈Z,y∈Z,即横 坐标是 0 到 19 (包含 0 和 19) 之间的整数、纵坐标是 0 到 20 (包含 0和 20​) 之 间的整数的点。

请问这些点一共确定了多少条不同的直线。

通过记录斜率和截距来判断有多少直线是同一条,由于计算有误差所以大于一个极小数即可,最后加上竖线的数量

#include 
#include
#include
#include
using namespace std;

const int N=200000;
int n;
struct Line
{
  double k,b;//斜率 截距
  bool operator< (const Line& t) const
  {
    if(k!=t.k ) return k1e-8||fabs(l[i].b-l[i-1].b)>1e-8)
      res++;
    }
  cout<

4. 货物摆放

小蓝有一个超大的仓库,可以摆放很多货物。

现在,小蓝有 n 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。

小蓝希望所有的货物最终摆成一个大的长方体。即在长、宽、高的方向上分别堆 L、W、H 的货物,满足 n=L×W×H。

给定 nn,请问有多少种堆放货物的方案满足要求。

例如,当 n=4n=4 时,有以下 66 种方案:1×1×4、1×2×2、1×4×1、2×1×2、2×2×1、4×1×1。

请问,当 n=2021041820210418 (注意有 16 位数字)时,总共有多少种方案?

解题思路

三个数相乘==n所以这三个数肯定都是n的约数,我们将所有约数记录到数组里,然后枚举这三个数即可判断相乘是否可以等于n即可

#include 
#include
// #include
#include
#include
using namespace std;
int main()
{
    // 请在此输入您的代码
    long long  n = 2021041820210418;
    
    vector d;
    
    for(long long i=1;i*i<=n;i++)
    {
      if(n%i==0)
      {
        d.push_back(i);

        //n/i也是n的一个约数
        if(n/i!=i) d.push_back(n/i);//节省枚举次数
      }
    }
    int res=0;
    
    //c可以不枚举
    for(auto a:d)
      for(auto b:d)
        for(auto c:d)
          if(a*b*c==n)
          res++;

    cout<

5. 路径

小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图 中的最短路径。

小蓝的图由 2021 个结点组成,依次编号 1 至 2021。

对于两个不同的结点 a, b,如果 a 和 b 的差的绝对值大于 21,则两个结点 之间没有边相连;如果 a 和 b 的差的绝对值小于等于 21,则两个点之间有一条 长度为 a 和 b 的最小公倍数的无向边相连。

例如:结点 1 和结点 23 之间没有边相连;结点 3 和结点 24 之间有一条无 向边,长度为 24;结点 15 和结点 25 之间有一条无向边,长度为 75。

请计算,结点 1 和结点 2021 之间的最短路径长度是多少。

解题思路

spfa来算出起点1到终点2021的最短路径,a,b的最小公倍数=a*b/gcd(a,b)

将符合题目的两个点添加到邻接表中,进行spfa算法即可

#include 
#include
#include
#include
using namespace std;

vector> E[2040];
int d[2040];//记录起点到别的点的长度
int inq[2040];//记录是否在队列里

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}
void spfa(int s, int t)
{
    memset(d, 0x3f, sizeof d);
    d[s] = 0;
    queue qu;
    qu.push(s);//入队
    inq[s] = 1;//表示s在队列中

    while (!qu.empty())
    {
        int now = qu.front();//
        qu.pop();
        inq[now] = 0;//不在队列里面了
        for (int i = 0; i < E[now].size(); i++)
        {
            int v = E[now][i].first;//取要去的城市

            if (d[v] > d[now] + E[now][i].second)//原来记录的长度,比现在这个城市到v的长度长就更新最短长度
            {
                d[v] = d[now] + E[now][i].second;

                if (inq[v] == 1)//已经在队列中了
                    continue;
                inq[v] = 1;
                qu.push(v);//入队
            }

        }
    }

     if(d[t]==1e9)
     cout<<-1<

6. 时间显示

小蓝要和朋友合作开发一个时间显示的网站。

在服务器上,朋友已经获取了当前的时间,用一个整数表示,值为从 1970 年 1 月 1 日 00:00:00 到当前时刻经过的毫秒数。

现在,小蓝要在客户端显示出这个时间。小蓝不用显示出年月日,只需要显示出时分秒即可,毫秒也不用显示,直接舍去即可。

给定一个用整数表示的时间,请将这个时间对应的时分秒输出。

解题思路

1秒=1000毫秒。计算小时就是/60再/60得到多少小时,模除24即可

计算分钟将小时去除掉,/60 去掉余下的秒数就是分钟数

计算秒 将小时去除掉,%60 取余数就是秒数

#include 
#include
using namespace std;

int main()
{
  // 请在此输入您的代码
  long long  ti;
  scanf("%lld",&ti);
  long long h,m,s;
  h=ti/1000/60/60%24;
  
  m=ti/1000%3600/60;//
  s=ti/1000%3600%60;
  
  printf("%02lld:%02lld:%02lld",h,m,s);
  // cout<

7. 砝码称重

你有一架天平和 N 个砝码,这 N 个砝码重量依次是 W1,W2,⋅⋅⋅,WN。

请你计算一共可以称出多少种不同的重量? 注意砝码可以放在天平两边。

解题思路

背包问题,C++:背包问题习题-CSDN博客 第四题

#include 
#include
#include
using namespace std;

bool f[110][100010];//表示前i个砝码,凑j的重量是否可以凑成
int n;
int w[110];//每个砝码重量
int main()
{
  // 请在此输入您的代码
  scanf("%d",&n);

  int res=0;
  for(int i=1;i<=n;i++)
  {
    scanf("%d",&w[i]);
    res+=w[i];
  }

  f[0][0]=true;
  for(int i=1;i<=n;i++)
  {
      for(int j=0;j<=res;j++)
      {
        f[i][j]=f[i-1][j]||f[i-1][abs(j-w[i])]||f[i-1][j+w[i]];//放在左边和放在右边
      }
  }
  int cnt=0;

  for(int i=1;i<=res;i++)
  if(f[n][i])
  cnt++;

  cout<

这篇就到这里啦(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤

你可能感兴趣的:(算法,c++,蓝桥杯)