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])
未完待续