第十二届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组

1. 空间  

签到水题,单位换算

#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
	cout<<(int)256*1024*1024*8/32<<endl; 
	return 0;
}
 


2. 卡片  

打表找规律,先存取所有可能的结果

// k种卡片组成 两两组合分给n  k*(k+1)/2 >= n
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
vector<int>nums;
signed main()
{
	cin>>n;
	for(int i=1; i<=1000000; i++) //找出k对应n所有情况
	{
		nums.push_back(i*(i+1)/2);
	}
	for(int i=0; i<nums.size(); i++)
	{
		if(nums[i]>=n)
		{
			cout<<i+1<<endl;
			break;
		}
	}
	return 0;
}


3. 直线  

数学知识,对于直线的确定,暴力遍历所有可能,需要特别注意斜率为0的情况

#include <bits/stdc++.h>
#define int long long
using namespace std;

set<pair<int, int>> nums; // 存储坐标
set<pair<double, double>> nums1; // 存储斜率截距

signed main()
{
	int n,m; 
	cin>>n>>m;
	// 插入坐标点
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			nums.insert({i, j});
		}
	}
	// 使用迭代器两两组合坐标点,计算斜率和截距
	vector<pair<int, int>> points(nums.begin(), nums.end());
	for (size_t i = 0; i < points.size(); i++)
	{
		for (size_t j = i + 1; j < points.size(); j++)
		{
			int x1 = points[i].first, y1 = points[i].second;
			int x2 = points[j].first, y2 = points[j].second;
			if (x1 != x2)   // 防止除以零
			{
				double k = 1.0 * (y2 - y1) / (x2 - x1);
				double b=1.0*(x1*y2-x2*y1)/(x1-x2);
				nums1.insert({k, b}); 
			}
		}
	}
	cout << nums1.size()+n << endl; //20斜率不存在的情况(垂直) 
	return 0;
}


4. 货物摆放  

数学知识,首先求出所有可能的因子情况,最后暴力遍历确定可能的结果,排列

//求出因子总数n   再求三位数全排列 
#include<bits/stdc++.h>
#define int long long
using namespace std;
int sum=0;
vector<int>nums;
const int n=2021041820210418;
signed main()
{
	for(int i=1; i*i<=n; i++)
	{
		if(n%i==0)
		{
			nums.push_back(i);
			if(i!=n/i)
			{
				nums.push_back(n/i);
			}
		}
	}
	for(int i=0; i<nums.size(); i++)
	{
		for(int j=0; j<nums.size(); j++)
		{
			for(int k=0; k<nums.size(); k++)
			{
				if(n==(int)nums[i]*nums[j]*nums[k])
				{
					sum++;
				}
			}
		}
	}
	cout<<sum<<endl;
	return 0;
}


5. 路径  

动态规划思想

#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
	int f[2030]; //遍历出所有情况 
	memset(f,0,sizeof(f));
	for(int i=1;i<=2021;i++)
	{
		for(int j=i+1;j<=i+21 && j<=2021;j++)
		{
			if(f[j]==0) f[j]=f[i]+i*j/__gcd(i,j);  
			else f[j]=min(f[j],f[i]+i*j/__gcd(i,j)); //多条路径到同一点 
		}
	}
	cout<<f[2021]<<endl;
	return 0;
}


6. 时间显示  

签到水题,有两个需要注意点:

1.除法会自动转为浮点运算(所以不要同时操作乘除法)

2.补全前导0的方法:printf("%02d:%02d:%02d\n",h,m,s);   补零两位输出 

//1h=3600*1000ms  24h=86400*1000ms 
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,t1=0,day=0,h=0,m=0,s=0;
signed main()
{
	cin>>t;
	day=t/86400000; //天数,注意:除法会自动转为浮点运算 
	t1=t%86400000; //剩余毫秒数 
	h=t1/3600000;
	m=t1%3600000/60000;
	s=t1%60000/1000;
	printf("%02d:%02d:%02d\n",h,m,s); 
	return 0;
}
 


7. 砝码称重  

不会做,看题解是动态规划实现的,下面是题解代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll N;
ll a[200];
ll summ=0;
ll ans=0;
int dp[200][200000];
//dp[i][j]表示用到前i个砝码,能否称出j重量
//1为可以,0为不可以

int main()
{
  // 请在此输入您的代码
  cin>>N;
  for(int i=1;i<=N;i++){
    cin>>a[i];
    summ+=a[i];
  }

  for(int i=1;i<=N;i++){
    for(int j=1;j<=summ;j++){//遍历所有可能的重量
      dp[i][j]=dp[i-1][j];//继承前一个状态
      if(dp[i][j]==0){//如果普通继承下来,发现这个不行呢?
        if(j==a[i]) dp[i][j]=1;//如果需要的重量正好就是第i个砝码,那么可以
        if(dp[i-1][j+a[i]]==1) dp[i][j]=1;//如果前i-1个能搞出j+a[i]重量,那么把第i个砝码放到另一侧就行
        if(dp[i-1][abs(j-a[i])]==1) dp[i][j]=1;//如果前i-1个砝码能搞出abs(j-a[i])重量
        //那么把第i个砝码放同侧就行
      }
    }
  }

  for(int j=1;j<=summ;j++){
    if(dp[N][j]==1) ans++;//遍历,看dp[][]==1的个数,就是答案
  }
  cout<<ans<<endl;
  return 0;
}

 
8. 杨辉三角形  

没做出来,只能过40%,下面给出我的代码(正常人能想到的不用算法的方法)和正确题解(二分)

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int a[10010][10010]; 
signed main()
{
	cin>>n;
	a[1][1]=1;
	for(int i=2;i<=10000;i++)
	{
		for(int j=1;j<=i;j++)
		{
			a[i][j]=a[i-1][j-1]+a[i-1][j];
		}
	}
	int sign=0;
	for(int i=1;i<=10000;i++)
	{
		for(int j=1;j<=i;j++)
		{
			sign++;
			if(a[i][j]==n)
			{
				cout<<sign<<endl;
				return 0;
			}
		}
	}
	return 0;
}
 
#include <stdio.h>
#include <stdlib.h>
int n;
int max(int a,int b)
 {
   if(a>b) return a;
   else return b;
 }
long long int fact(int a,int b)
{
  long long int x=1;
   for(int i=a,j=1;j<=b;i--,j++)
   {
     x=x*i/j;
     if(x>n) return x;
   }
   return x;
}
 int find(int k)
 {
   long long int l=2*k,r=max(n,l);
   long long int c;
   while(l<r)
   {
     int mid=(l+r)/2;
     if(fact(mid,k)>=n) r=mid;
     else l=mid+1;
   }
   if(fact(r,k)!=n) 
   {
       return 0;
   }
   else 
   {
     c=(r*(r+1))/2+k+1;
     printf("%lld",c);
     return 1;
   }
 }

int main()
{
  // 请在此输入您的代码
  scanf("%d",&n);
  for(int i=16; ;i--)
  {
    if(find(i)) break;
  }
  return 0;
}


9. 双向排序  

我的代码能过60%,正确题解得使用线段树(不是很会),感兴趣的可以去官方看

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a[1000010];
signed main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) 
	{
		a[i]=i;
	}
	while(m--)
	{
		int p,q;
		cin>>p>>q;
		if(p==0) //a1...aq降序
		{
			sort(a+1,a+1+q,greater<int>());
		}
		else //aq...an升序
		{
			sort(a+q,a+1+n);
		}
	}
	for(int i=1; i<=n; i++)
	{
		cout<<a[i]<<" ";
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值