第十二届蓝桥杯c++b组

问题 - New Online Judge

 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值