目录
1.空间
2.直线
3.路径
4.卡片
5.货物摆放
6.时间显示
7.砝码称重
8.杨辉三角
9.双向排序
10.括号序列
1.空间
题目解析:1Byte = 8bit 1kb = 1024B 1MB = 1024kb;
先将256MB变成Byte = 256 * 1024 * 1024; 再将32位 变成Byte就是 32 / 8 = 4;
那么就是(256 * 1024 * 1024) / 4 = 67108864;
2.直线
题目解析:直线方程式y= kx + b;
k = (y2 - y1) / (x2 - x1);
b = (y1 * x2 - y2 * x1) / (x2 - x1);
使用double类型怕精度损失。再使用set进行去重。最后还要考虑垂直和平行的情况就要加上m + n;
#include <iostream>
#include<set>
using namespace std;
set<pair<double,double>> s;
void check(int x1, int y1, int x2, int y2)
{
if(x1 == x2 || y1 == y2)//平行或者垂直;
return;
double k = (y2 - y1) * 1.0 / (x2 - x1);
double b = (y1 * x2 - y2 * x1) * 1.0 / (x2 - x1);
s.insert({k, b});
}
int main()
{
for(int x1 = 0; x1 < 20; x1++)
{
for(int y1 = 0; y1 < 21; y1++)
{
for(int x2 = 0; x2 < 20; x2++)
{
for(int y2 = 0; y2 < 21; y2++)
{
check(x1, y1, x2, y2);
}
}
}
}
cout << s.size() + 20 + 21<< endl;
return 0;
}
3.路径
题目解析:采用到一个弗洛伊德算法。大家可以自己再csdn里面看一下弗洛伊德算法求图的路径的博客,就很容易上手这个题目.使用二维数组进行存放连接的点。这个使用三次暴力可以在devc++里面跑几十秒就过了,但是在蓝桥杯官网会超时.但是这不重要,重要的是这是个填空题.
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
#define INT 0x3f3f3f3f
ll Edge[2022][2022];
int gcd(int a, int b)//最大公约数
{
if (b == 0)
return a;
return gcd(b, a % b);
}
int lcm(int a, int b)//最小公倍数
{
int c = a * b;
return c / gcd(a, b);
}
int main()
{
//初始化
memset(Edge, INT, sizeof(Edge));
for (int i = 1; i <= 2021; i++)
{
for (int j = 1; j <= 2021; j++)
{
if (i == j)Edge[i][j] = 0;
else {
if (abs(i - j) <= 21)//判断差的绝对值是否小于等于21
{
Edge[i][j] = lcm(i, j);
}
}
}
}
for (int k = 1; k <= 2021; k++)
{
for (int i = 1; i <= 2021; i++)
{
for (int j = 1; j <= 2021; j++)
{
if (Edge[i][j] > Edge[i][k] + Edge[k][j])
{
Edge[i][j] = Edge[i][k] + Edge[k][j];
}
}
}
}
cout << Edge[1][2021];
return 0;
}
4.卡片
题目解析:动态dp又来罗, dp[i]表示i张卡片不重复的数量,并且我们可以弄出状态方程.
1张: 1;
2张: (1,1), (1,2),(2,2); 三种不重复的数量,
3张: (1,1), (1,2), (2,2), (1,3), (2,3), (3,3); 就是六种不重复的数量,
那么状态方程dp[i] = ap[i - 1] + i;
#include <iostream>
#include<set>
using namespace std;
int dp[100000] = {0};
int main()
{
int n;
cin >> n;
dp[1] = 1;
for(int i = 2; i < 10000; i++)
{
dp[i] = dp[i - 1] + i;
if(n <= dp[i])
{
cout << i << endl;
return 0;
}
}
return 0;
}
5.货物摆放
题目解析:暴力解法,但是还有要稍加修改。如果三个数中有两个是相同的那么一共有三种方法,如果三个数都不同就会有六种方法,三个数全部相同不符合题目意思。这个也是蓝桥杯官网跑不了,但是dev可以等个几十秒就出来了.
#include<iostream>
using namespace std;
#define n 2021041820210418
//n=a*b*c
typedef long long ll;
int ants = 0;
int main()
{
for (ll a = 1; a * a * a <= n; a++)
{
if (n % a == 0)
{
for (ll b = a; a * b * b <= n; b++)
{
if (n / a % b == 0)
{
ll c = n / a / b;
if (a == b && a == c)ants = 0;
else if (a == b || a == c || c == b) ants += 3;
else ants += 6;
}
}
}
}
cout << ants << endl;
return 0;
}
6.时间显示
题目解析:根据题目意思进行划时间,但是输入的是毫秒需要变成秒。如果觉得很容易想错,你可以想一下有一个题目提取数字的每一位.
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long int n;
cin >> n;
n = n / 1000;
n = n % 86400;//去掉除了最后一天的前面的天数;24*60*60
int h, m, s;
h = n / 3600;//求得最后一天的小时
n = n % 3600;
m = n / 60;//分钟
s = n % 60;//秒数
printf("%02d:%02d:%02d",h,m,s); //输出时间常用的形式,不用判断了
return 0;
}
7.砝码称重
题目解析:背包问题,采用动态dp,dp[i][j]表示第i个砝码拿到重量j的方案。如果第i-1个砝码可以拿到j个重量那么i个砝码也可以拿到j个重量, 同样i也可以拿到j重量加上/减去输入的砝码的重量,最后只要将可以称重的砝码进行加和就可以算出结果.
#include <iostream>
#include<cmath>
using namespace std;
int dp[105][100005];
int main()
{
int n;
cin >> n;
//从前i个物品中拿到总重量是j的集合。
dp[0][0] = 1;
for(int i = 1; i <= n; i++)
{
int a;
cin >> a;
for(int j = 0; j <= 100000; j++)
{
if(dp[i - 1][j])
{
dp[i][j] = 1;
dp[i][j + a] = 1;
dp[i][abs(j - a)] = 1;
}
}
}
int ans = 0;
for(int i = 1; i <= 100000; i++)
{
if(dp[n][i])
ans++;
}
cout << ans << endl;
return 0;
}
8.杨辉三角
题目解析: 这里开始就变得不妙了,这题只过了部分用例,又更好的办法挺难想到的,大家可以看看其他佬的博客.鄙人不才写不出来.
观察上面的规律之后我们可以使用两个数组进行查找.两个数组不断变化每一层,我们就可以得到每一层的数据的位置.
#include <iostream>
using namespace std;
#include<vector>
vector<long long int> v1;
long long int n;
long long int ans = 0;//算n的位置的.
int main()
{
cin >> n;
if(n == 1)
{
cout << 1 << endl;
return 0;
}
v1.push_back(1);
ans++;
for(int i = 0; i < v1.size(); i++)
{
vector<long long int> v2;
if(i == 0)
{
v2.push_back(1);
ans++;
}
else
{
ans++;
if(n == v1[i - 1] + v1[i])
{
cout << ans << endl;
return 0;
}
v2.push_back(v1[i - 1] + v1[i]);
}
ans++;
v2.push_back(1);
v2 = v1;
}
return 0;
}
9.双向排序
题目解析:直接用sort进行排序.其他方法又会的大佬麻烦教教我,阿里嘎多.
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,p,q;
int a[100005];
int cmp(int x, int y)
{
return x > y;
}
int main()
{
cin >> n >> m;
for(int i = 0; i < n; i++)
{
a[i] = i+1;
}
while( m > 0 )
{
m--;
cin >> p >> q;
if(p == 0)
{
sort(a, a+q, cmp); // 逆排
}
else
{
sort(a+q-1, a+n); // 正排
}
}
for(int i = 0; i < n; i++)
cout << a[i] << " ";
return 0;
}
10.括号序列
题目解析:这里贴一篇博主的优质博客大家看看吧,自己太菜了,还得多练练.
括号序列--蓝桥杯_括号序列蓝桥杯-CSDN博客
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stdio.h>
using namespace std;
typedef long long LL;
const int MOD=1000000007;
const int N=5010;
LL dp[N][N];
char str[N];
int len;
LL func()
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=len;i++)//一个括号一个括号的判断
{
if(str[i]=='(')
{
for(int j=1;j<=len;j++)
{
dp[i][j]=dp[i-1][j-1];//不用考虑dp[i][0] 因为dp[i-1][-1]是不合法的情况 不存在 为0
}
}
else
{
dp[i][0]=(dp[i-1][0]+dp[i-1][1])%MOD;//特判防止越界 这里数据短,用的是优化前的推断
for(int j=1;j<=len;j++)
{
dp[i][j]=(dp[i-1][j+1] + dp[i][j-1])%MOD;
}
}
}
for(int i=0;i<=len;i++)
if(dp[len][i]) return dp[len][i];//我们需要的就是长度为len添加括号的合法情况,而从前往后遍历出现的第一个有可能的情况就是需要括号数最少的情况,因为左括号可以加很多个,我们仅需添加最少的情况
return -1;
}
int main()
{
scanf("%s",str+1);//从下标为1开始
len=strlen(str+1);
LL l=func();
reverse(str+1,str+len+1);
for(int i=1;i<=len;i++)
{
if(str[i]=='(') str[i]=')';
else str[i]='(';
}
LL r=func();
cout<<l*r%MOD;
return 0;
}