1.空间
P1555 - [蓝桥杯2021初赛] 空间 - New Online Judge (ecustacm.cn)
1MB=1024KB
1KB=1024B(byte字节)
1B(byte字节)=8b(bit位)
256*1024*1024*8/32=67108864
要注意,运算符的参数默认为int类型,因此在运算过程中,可能就超出了int范围,数据就在途中变了
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
int main()
{
LL m=1;
m=256*1024;
m*=1024;
m*=8;
m/=32;
cout<<m<<endl;
return 0;
}
2.卡片
P1550 - [蓝桥杯2021初赛] 卡片 - New Online Judge (ecustacm.cn)
开10个数组,下标为0到9,代表卡片上的数字,a[0]到a[9]都赋值为2021,表示都有2021张卡片
从1开始遍历,对于每一个数,求它的所有位,然后相应的,卡片一张一张消耗,如果遇到哪张卡片消耗成了-1,说明这个数i是拼不成的,那么就输出i-1,并且可以退出循环了
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[20];
int main()
{
for(int i=0;i<10;i++){
a[i]=2021;
}
for(int i=1;;i++){
int n=i;
while(n){
int x=n%10;
a[x]--;
if(a[x]<0){
cout<<i-1<<endl;
return 0;
}
n/=10;
}
}
return 0;
}
3.货物摆放
P1552 - [蓝桥杯2021初赛] 货物摆放 - New Online Judge (ecustacm.cn)
首先,因为是结果填空题,虽然有时间限制,但是设计程序时间稍长一些也没关系,只要能得出结果就行,最后把结果提交就好了
为保证不重复计数,使得三个数i<=j<=x(保证三个数都是n的因子),然后如果全部相等,计数加1,两个相等,计数加3,三个都相等,计数加6
注意数据类型要long long
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
int main()
{
LL res=0;
LL n=2021041820210418;
for(LL i=1;i<=sqrt(n);i++){
if(n%i==0){
LL m=n/i;
for(LL j=i;j<=sqrt(m);j++){
if(m%j==0){
LL x=m/j;
if(j<=x){
if(i==j&&j==x){
res+=1;
}
if(i==j&&i!=x){
res+=3;
}
if(j==x&&i!=j){
res+=3;
}
if(i!=j&&j!=x){
res+=6;
}
}
}
}
}
}
cout<<res<<endl;
return 0;
}
4.直线
P1551 - [蓝桥杯2021初赛] 直线 - New Online Judge
用斜截式,对于每两个点,可以求出它们所连直线的斜率以及截距,只需判断有多少对不同的斜率和截距就行了,特殊的,对于斜率不存在的直线特判一下(一共有20条)
但是要注意,浮点数精度问题可能导致相同的浮点数会有些许差距,并不完全相同,我们认定当两个浮点数的差大于1e-8时两者为不同数,反之则为相同数
将斜率和截距放在一个结构体中,排个序,然后如果前后不相等则说明不为同一直线,则计数加1,最后再加上20条斜率不存在的直线
一共四百个点左右,那么在400个点中任取两个点有400*399/2条直线
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=200010;
int n;
struct Line{
double k,b;
bool operator<(const Line &W)const{
if(k!=W.k) return k<W.k;
return b<W.b;
}
}l[N];
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++){
if(x1!=x2){
double k=(double)(y2-y1)/(x2-x1);
double b=y1-k*x1;
l[n++]={k,b};
}
}
}
}
}
sort(l,l+n);
int res=1;
for(int i=1;i<n;i++){
if(fabs(l[i].k-l[i-1].k)>1e-8||fabs(l[i].b-l[i-1].b)>1e-8) res++;
}
cout<<res+20<<endl;
return 0;
}
5.路径
P1553 - [蓝桥杯2021初赛] 路径 - New Online Judge
一共2021个点,每个点最多连42个点,数组可以开稍大一些
用最短路模板,可以用spfa
求最小公倍数,可以先求两个数的最大公约数,再将两数相乘并除以最大公约数
最大公约数用辗转相除法
int gcd(int a,int b){
if(b==0) return a;
return gcd(b,a%b);
}
求最大公约数,该函数a,b大小顺序没关系,不过在记忆的时候,不妨认为a(左边)大于b(右边),然后求最大,肯定返回大的a
用大的a去对小的b取余
大的b写左边,小的a%b写右边
(用于记忆)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=2200,M=N*50;
int n;
int h[N],e[M],w[M],ne[M],idx;
int dist[N];
bool st[N];
int gcd(int a,int b){
if(b==0) return a;
return gcd(b,a%b);
}
void add(int a,int b,int c){
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int spfa(){
memset(dist,0x3f3f3f3f,sizeof dist);
dist[1]=0;
queue<int>q;
q.push(1);
st[1]=true;
while(q.size()){
int t=q.front();
q.pop();
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(dist[j]>dist[t]+w[i]){
dist[j]=dist[t]+w[i];
if(!st[j]){
q.push(j);
st[j]=true;
}
}
}
}
return dist[n];
}
int main()
{
n=2021;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++){
for(int j=max(1,i-21);j<=min(n,i+21);j++){
int d=gcd(i,j);
add(i,j,i*j/d);
}
}
spfa();
cout<<dist[n]<<endl;
return 0;
}
6.砝码称重
P1558 - [蓝桥杯2021初赛] 砝码称重 - New Online Judge
有限制的选择问题(背包问题)
天平两边都可以放,放左边是负的,放右边是正的 ,不放是0
状态表示:f[i][j]表示只从前i个砝码中选,且总重量为j的所有方案的集合 ,属性为是否非空(bool类型)
状态计算:分成3类,不选,选正的(放右边) ,选负的(放左边)
不选:f[i-1][j]
选正wi:f[i-1][j-wi](j-wi一定得大于等于-m,不然都没有状态能转移过来)
选负wi:f[i-1][j+wi](j+wi一定得小于等于m)
只要这三种可能有一个非空,那么f[i][j]就非空(用或等于,|=,有一个为true,就为true)
只要考虑f[n][1到m]有多少个非空(m为所有砝码的总质量)
注意,j的取值是-m<=j<=m,但数组元素下标不能为负数,因此加个偏移量,使之全部为正数
M应大于j取值范围,B 为偏移量(所有第二维都要加B)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=110,M=200010,B=M/2;
int n,m;
int w[N];
bool f[N][M];
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>w[i];
m+=w[i];
}
f[0][B]=true;
for(int i=1;i<=n;i++){
for(int j=-m;j<=m;j++){
f[i][j+B]=f[i-1][j+B];
if(j-w[i]>=-m) f[i][j+B]|=f[i-1][j+B-w[i]];
if(j+w[i]<=m) f[i][j+B]|=f[i-1][j+B+w[i]];
}
}
int res=0;
for(int j=1;j<=m;j++){
if(f[n][j+B]) res++;
}
cout<<res<<endl;
return 0;
}
7.时间显示
P1563 - [蓝桥杯2021初赛] 时间显示 - New Online Judge
用总的毫秒数除以一小时的毫秒数再对24取余,得到小时
用总的毫秒数除以一分钟的毫秒数再对60取余,得到分钟
用总的毫秒数除以一秒的毫秒数再对60取余,得到秒
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
int main()
{
int t;
cin>>t;
while(t--){
LL m;
scanf("%lld",&m);
int x=m/(3600*1000)%24;
int y=m/(60*1000)%60;
int z=m/(1000)%60;
printf("%02d:%02d:%02d\n",x,y,z);
}
return 0;
}