蓝桥杯往期水题自我总结

1.卡片
1是最先被消耗的,所以只需要判断1什么时候被消耗掉即可

我的易错点:
每次在最后会把答案 cnt 多加一次
导致最后的结果比正确答案多1
在最后应该再判断一次

可能是因为平时打代码的坏习惯,每次这儿都反应不过来

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

和几进制无关,跟位数有关,32位就是32bit
所以 先把256MB换算成 KB,再把KB换算成B,1B=8bit

256*1024*1024*8/32

3.带宽
小蓝家的网络带宽是 200 Mbps,请问,使用小蓝家的网络理论上每秒钟最多可以从网上下载多少 MB 的内容。

需要注意的是贷款的单位是 200Mbps,这里的b是小写的b
所以直接200/8,把b换算成B即可

25

4.货物摆放
这个题是把 N分解成三个因子
第一点需要注意,分解成三个因子,只需要用两个根号循环找出
两个因子即可

第二点是防止出现重复,所以最后我们只记录 c>=b&&b>=a的因子
第三点是需要对因子进行排列组合

long long a,b,c;
a=i,b=j,c=temp/j;

if(c>=b&&b>=a) {
	if(a!=b&&b!=c&&c!=a)
		sum+=6;
	else if(a==b&&b==c)
		sum+=1;
	else if((a==b&&b!=c)||(a==c&&c!=b)||(b==c&&c!=a))
		sum+=3;
}

5.路径

普通的暴力迪杰斯特拉即可

唯一需要注意的是:有些时候,需要从一些高节点,回退到低节点
所以在迪杰斯特拉的时候,要把这个点能到达的所有点全考虑进去。

6.砝码称重

如果不允许放在天平的两侧,只允许放在天平的一侧:

如果是多重背包,且只允许放在其中一侧:

for(int i=1;i<=n;i++)
  for(int j=sum;j>=m[i];j--)
     for(int k=1;k<=num[i];k++)
     { 
         if(dp[j-k*m[i]]==1)
         { 
            dp[j]=1;
         }
     }

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

请你计算一共可以称出多少种不同的重量?

注意砝码可以放在天平两边。

由于可以放在天平的两侧,所以不能当成单纯的 0 1背包处理
第二层循环需要正序枚举

for(int i=1;i<=n;i++)
  for(int j=1;j<=sum;j++)
     dp[i][j]=dp[i-1][j];//继承上一层的状态;
     if(dp[i-1][j]==0)
     {
          if(j==a[i])//说明新加入的砝码重量正好等于 目标重量
          dp[i][j]=1;
          if(dp[i][j+a[i]])  //砝码放在不同侧,通过相减得出目标重量
          dp[i][j]=1;
          if(dp[i][abs(j-a[i])])  //放在相同侧,或者不同侧,
          dp[i][j]=1;
     }

int cnt=0;
for(int i=1;i<=sum;i++)
{
  if(dp[n][i])
  cnt++; 
 }

7.相乘
小蓝发现,他将 1 至 1000000007 之间的不同的数与 2021 相乘后再求除以1000000007 的余数,会得到不同的数。

小蓝想知道,能不能在 1 至 1000000007 之间找到一个数,与 2021 相乘后再除以 1000000007 后的余数为 999999999。如果存在,请在答案中提交这个数;如果不存在,请在答案中提交 0。

纯纯的暴力即可:

值得一提的是,枚举i的时候,必须用long long 类型。
如果改用int 类型会不出结果!!!!!!!
for(long long i=1;i<=1000000007;i++)  //这里必须是long long 类型
     {
     	long long x=i*2021; 
     	if(x%1000000007==999999999)
     	{
     		cout<<i;
     		return 0;
		}
	 }

8.最少砝码
你有一架天平。现在你要设计一套砝码,使得利用这些砝码可以称出任意小于等于 N 的正整数重量。

那么这套砝码最少需要包含多少个砝码?

注意砝码可以放在天平两边。

规律题:
1 4 13 40  所需要的砝码分别为
1 2 3 4
 for(int i=1;i<=1000000;i++)
	{
		double a=(pow(3,i)-1)/2;
		double b=(pow(3,i-1)-1)/2+1;
		
		if(n<=a&&n>=b)
		{
			cout<<i;
			break;
		}
	}

9.直线
求出一共确定了多少条不同的直线

误区:
如果使用 y=kx+b,这样的式子求斜率和截距,
先求出k,然后用k求b
然后用map标记之后,就会错掉

然是如果使用式子
y= (y2-y1)/(x2-x1) x+ (x1*y2-x2*y1)/(x1-x2);
式子 k=(y2-y1)/(x2-x1)
b=(x1*y2-x2*y1)/(x1-x2)  然后用map标记即可

10.纯质数

一个素数筛就可以暴力解决,没有难度
但是要注意的是,一定要记得把0标记,把0标记成非素数

11.完全日期

注意是把日期的每一位加起来,而不是把年月日加起来

12.异或变换
小蓝有一个 01 串 s=s1s2s3…sn。

以后每个时刻,小蓝要对这个 01 串进行一次变换。每次变换的规则相同。对于 01 串 s=s1s2s3…sn,变换后的 01 串s’=s′_1 s′_2 s′_3 \ldots s′_n$ 为:

s’1=s1;

s’i=si−1⊕si。

其中 a⊕b 表示两个二进制的异或,当a和 b 相同时结果为 0,当 a 和b不同时结果为 1。

请问,经过 t 次变换后的 01 串是什么?

也是一个规律题
本来其实是完全没有思路的,但是看了题解之后
题解说这是一个周期题,所以说按照题目要求的变换时会有周期的


!!!!通过打表得到一个长度为n的01串的循环节为最小的大于等于n的2整数次幂。
for(int i=1; i<=n; i++) {
	a[i]=s[i-1]-'0';
}

long long c=1;
while(c<n) {
	c=c*2;
}   //周期是最小的大于等于n的2的整数次幂
t=t%c;
while(t--) {
	for(int i=n; i>=2; i--) {
		a[i]^=a[i-1];
	}
}

总结:如果一个题完全找不到规律,可以先缩小范围,打一个表,做一个假设。

13.最小权值
对于一棵有根二叉树 T,小蓝定义这棵树中结点的权值 W(T) 如下:

空子树的权值为 0。

如果一个结点 v 有左子树 L, 右子树 R,分别有 C(L) 和 C® 个结点,则

W(v)=1+2W(L)+3W( R )+(C(L))2C( R )

一个C++思路正确,但是过不去的代码:
#include<bits/stdc++.h>
using namespace std;
long long dp[3000];
int main() {
	dp[0]=0;

	for(int i=1; i<=2021; i++) { 
		dp[i]=0x3f3f3f3f;
		for(int j=0; j<i; j++) {  //枚举左子树的个数,如果左子数的个数位j,那么右子树的个数即为i-j-1 //因为有一个节点是根节点。
			dp[i]=min(dp[i],1+2*dp[j]+3*dp[i-j-1]+j*j*(i-j-1));
		}
	}

	cout<<dp[2021];
	return 0;
}

但是由于dp过程会爆long long
所以只能用python做

 dp = [0]
    for i in range(1, 2022):
        dp.append(sys.maxsize)
        for j in range(i):
            dp[i] = min(dp[i], 1 + 2 * dp[j] + 3 * dp[i - 1 - j] + j * j * (i - 1 - j))
    print(dp[2021])

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值