第九届蓝桥杯

一.第几天

题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
2000 年的 1 月 1 日,是那一年的第 1 天。那么,2000 年的 5 月 4 日,是那一年的第几天?
点击查看代码
#include <iostream>
using namespace std;
int main()
{
  cout<<31+31+29+34;
  return 0;
}

思路:2000年是闰年,二月29天,加上两个31和一个4就是答案。

二.明码

题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
汉字的字形存在于字库中,即便在今天,16 点阵的字库也仍然使用广泛。16 点阵的字库把每个汉字看成是 16×16 个像素信息。并把这些信息记录在字节中。一个字节可以存储 8 位信息,用 32 个字节就可以存一个汉字的字形了。 把每个字节转为 2 进制表示,1 表示墨迹,0 表示底色。每行 2 个字节,一共 16 行 这道题目是给你一段多个汉字组成的信息,每个汉字用 32 个字节表示,这里给出了字节作为有符号整数的值。题目的要求隐藏在这些信息中。你的任务是复原这些汉字的字形,从中看出题目的要求,并根据要求填写答案。
点击查看代码
#include <iostream>
using namespace std;
struct Character
{
    char bytes[32];
};
void printByte(char byte) {
    char bytes[8] = { 0 };
    for (int i = 7; i >= 0; --i) {
        bytes[i] = byte % 2;
        byte >>= 1;
    }
    for (int i = 0; i < 8; ++i) {
        if (bytes[i])
            cout << "*";
        else
            cout << " ";
    }
}
void printCharacter(char bytes[])
{
    for (int i = 0; i < 32; ++i)
    {
        printByte(bytes[i]);
        if (i != 0 && (i + 1) % 2 == 0)
            cout << endl;
    }
}
int main()
{
    for (int i = 0; i < 10; ++i)
    {
        printCharacter(characters[i].bytes);
        cout << endl;
    }
    return 0;
}

思路:将数据输入结构体中就能输出看到文字。

三.乘积尾零

题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可
如下的 10 行数据,每行有 10 个整数,请你求出它们的乘积的末尾有多少个零?
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int main()
{
	int num2 = 0, num5 = 0;
	for (int i = 0; i < 100; i ++)
	{
		int x;
		cin >> x;
		
	
		while(x % 2 == 0)
		{
			num2 ++;
			x /= 2;
		}
		
		
		while(x % 5 == 0)
		{
			num5 ++;
			x /= 5;
		}
	}
	

	cout << (num2 > num5? num5:num2) << endl;
	
	return 0;
}

思路:通过观察可知,需要 末尾为 5 与 末尾为 2、4、6、8 的数字相乘,而这样的数字可拆分为多个 2 与 5 相乘,例如 125 * 512 = 64000, 125 = 20 * 53, 512 = 29 * 50,于是 2 的个数为 9,5 的个数为 3,共有 3 对 2 * 5,所以结果为 3。

四.测试次数

题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
X 星球的居民脾气不太好,但好在他们生气的时候唯一的异常举动是:摔手机。各大厂商也就纷纷推出各种耐摔型手机。x星球的质监局规定了手机必须经过耐摔测试,并且评定出一个耐摔指数来,之后才允许上市流通。X 星球有很多高耸入云的高塔,刚好可以用来做耐摔测试。塔的每一层高度都是一样的,与地球上稍有不同的是,他们的第一层不是地面,而是相当于我们的 2 楼。如果手机从第 7 层扔下去没摔坏,但第 8 层摔坏了,则手机耐摔指 =7。 特别地,如果手机从第 1 层扔下去就坏了,则耐摔指数 =0。 如果到了塔的最高层第 n 层扔没摔坏,则耐摔指数 =n。为了减少测试次数,从每个厂家抽样 3 部手机参加测试。某次测试的塔高为 1000 层,如果我们总是采用最佳策略,在最坏的运气下最多需要测试多少次才能确定手机的耐摔指数呢? 请填写这个最多测试次数。

方法一:

点击查看代码

#include <iostream>
using namespace std;
const int M=1005,N=4;
int dp[M][N];
int main()
{
  int n=1000,m=3;
  for(int i=1;i<=n;++i)
  {
    dp[i][1]=i;
  }
  for(int j=2;j<=m;++j)
  {
    for(int i=1;i<=n;++i)
    {
      dp[i][j]=2e9;
      for(int k=2;k<=i;++k)
      {
        dp[i][j]=min(dp[i][j],1+max(dp[k-1][j-1],dp[i-k][j]));
      }
    }
  }
  cout<<dp[n][m];
  // cout<<19;
  return 0;
}

思路:动态规划,想象一下j=1的时候,我们dp[i][1]=i,因为我们不知道这个手机的性能怎么样,所以我们要从第一层一直往上走去试,第几层就是要试几次

那当j=2的时候呢?假设现在剩余k层,总层数是n,dp[k][2],那么有两种情况:

1.摔坏,dp[k][2]=dp[k][1]

2.没摔坏,dp[k][2]=dp[n-k][1],这里的n-k相当于把下面的层砍掉了

依据上面情况写出状态转移方程,上边的k代表的是从第几层开始摔。我们的目标是求采用最优策略,在最坏情况下确定次数,也就是说,在摔坏和没摔坏的两种情况下,我们要选大的,这体现了我们运气最差,之后从所有大的里边选最小的,体现了我们在所有策略里边选取最优的。

方法二:

思路:假设 第 1 次随便随便选一层扔 ,选 第 i_1 层 碎了,那么只好 从第1层 开始扔了

最坏就是 耐摔指数为 i_1-1 要1+i_1-1=i_1 次测试 (同时保证 i_1<=k) 若没碎就可以进行下一步

假设 第 2 次随便随便选一层扔 ,选第 i_2 层 碎了,那么只好 从第 i_1 +1层 开始扔了

最坏就是 耐摔指数为i_2 -1 要1+1+(i_2 -1)- i_1= i_2 -i_1+1 次测试(同时保证 i_2 -i_1+1 <=k)若没碎就可以进行下一步

假设 第 3次随便随便选一层扔 ,选第 i_3 层 碎了,那么只好 从第i_2 +1层 开始扔了

最坏就是 耐摔指数为 i_3 -1 要1+1+(i_3-1)-i_2 =i_3-i_2 +2 次测试 (同时保证 i_3-i_2 +2 <=k)若没碎就可以进行下一步

如果 只有一部手机给你测试 哪只能 从第一层开始扔 最坏情况就是 从1扔到 1000层去,最坏情况就是1000次

如果 只有二部手机给你测试 ,这时候 就相当于多了一次机会 可以博上一博 减少点测试次数(准确的说是减少最坏情况下的测试次数),这个时候就需要假设一下了 ,最坏测试次数为 k 次 ,也就是说 无论你手机的耐摔指数为多少(1000内), 我都能通过k次测试 找到,那么想想假设 第 1 次随便随便选一层扔 ,选 第 i_1 层 碎了,碎了我也有2部手机不是,那么 我此时想用两部手机测出 1~(i_1 -1)范围的耐摔指数就和上面情况一样的

最坏测试次数满足关系 k*(k+1)/2>=i_1-1= i_1-1 (同时保证 k+1<=K,===>k<=K-1注 :这是大 K )

若没碎就可以进行下一步

假设 第 2 次随便随便选一层扔 ,选第 i_2 层 碎了,碎了我也有2部手机不是,

那么 我此时想用两部手机测出 (i_1 +1)~( i_2-1)范围的耐摔指数就和上面情况一样的

最坏测试次数满足关系 k*(k+1)/2>=( i_2​​​​​​​-1)-i_1 =i_2​​​​​​​- i_1-1 (同时保证 k+1+1 <=K,===>k<=K-2注 :这是大 K)

若没碎就可以进行下一步

得出最后关系式,化简得1/2{ K(K+1)(2K+1)/6 -[K(K+1)-K(K+1)/2]>=i_k-K

                  ====>1/2*{   K*(K+1)(2K+1)/6 -[K*(K+1)-K*(K+1)/2]>=i_k-K

                  ====> (K^3+5K)/6 >= i_k==1000

得到公式后就能求出答案了。

五.递增三元组

题目描述
给定三个整数数组A = [A1, A2, … AN],B = [B1, B2, … BN],C = [C1, C2, … CN],请你统计有多少个三元组(i, j, k) 满足:1 <= i, j, k <= NAi < Bj < Ck
点击查看代码
#include <iostream>
#include <string>
using namespace std;
int m[3];
int sum = 0;

int main()
{
    memset(m,0,sizeof(m));
    int n;
    cin>>n;
    int *a = NULL;
    int *b = NULL;
    int *c = NULL;
    a = new int [n];
    b = new int [n];
    c = new int [n];
    int i;
    for(i=0;i<n;i++)
    {
        cin>>a[i];
    }
    for(i=0;i<n;i++)
    {
        cin>>b[i];
    }
    for(i=0;i<n;i++)
    {
        cin>>c[i];
    }
    for(i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            for(int k=0;k<n;k++)
            {
                m[0] = a[i];
                m[1] = b[j];
                m[2] = c[k];
                if(m[0]<m[1]&&(m[1]<m[2]))
                {
                    sum++;
                }
            }
        }
    }
    cout<<sum<<endl;
    return 0;
}

思路:暴力循环,输出满足条件的即可。

posted on 2025-03-31 23:02  好好好好好好好好好  阅读(21)  评论(0)    收藏  举报