第十二届蓝桥杯省赛B组部分题题解

第十二届蓝桥杯省赛B组部分题解


填空题

直线
#include<bits/stdc++.h>
using namespace std;
struct node{
    
    
	double xx;
	double yy;
	node(int cinx,int ciny){
    
    
		xx=cinx;
		yy=ciny;
	}
	node(double cinx,double ciny){
    
    
		xx=cinx;
		yy=ciny;
	}
	bool operator<(const node &y) const {
    
    
		if(xx==y.xx){
    
    
		    return yy < y.yy;
		}
		return xx < y.xx;
    }
};
map<node,bool> mp;
vector<node> v;

int main()
{
    
    
	int x,y;
	cin>>x>>y;
	int res=0;
	for(int i=0;i<x;i++){
    
    
		for(int j=0;j<y;j++){
    
    
			node x1=node(i,j);
			for(int p=0;p<x;p++){
    
    
				for(int q=0;q<y;q++){
    
    
					node y1=node(p,q);
					
					if(x1.xx==y1.xx&&x1.yy==y1.yy) continue;
					
					if(x1.xx!=y1.xx){
    
    
						int num1=y1.yy-x1.yy;
						int num2=y1.xx-x1.xx;
						double k=(y1.yy-x1.yy)*1.0/(y1.xx-x1.xx);
						double b=x1.yy-k*x1.xx;
						if(!mp.count(node(k,b))){
    
    
							mp[node(k,b)]=true;
							v.push_back(node(k,b));
						}
					}
				}
			}
		}
	}
	sort(v.begin(),v.end());
	for(int i=1;i<v.size();i++){
    
    
		if(fabs(v[i].yy-v[i-1].yy)>1e-8 || fabs(v[i].xx-v[i-1].xx)>1e-8)
			res++;
	}
	cout<<res+y<<endl;
	return 0;
}
//答案:40257
货物摆放(大数质数判断)
#include<bits/stdc++.h>
using namespace std;

int main()
{
    
    
	long long n;
	cin>>n;
	vector<long long> ans;
	for(long long i=1;i*i<=n;i++){
    
    
		if(n%i==0) {
    
    
			ans.push_back(i);
			if((n/i)!=i) ans.push_back(n/i);
		}
	}
	//for(int i=0;i<ans.size();i++) cout<<ans[i]<<" ";
	//cout<<endl;
	int res=0;
	for(int i=0;i<ans.size();i++){
    
    
		for(int j=0;j<ans.size();j++){
    
    
			for(int k=0;k<ans.size();k++){
    
    
				if(ans[i]*ans[j]*ans[k]==n) res++;
			}
		}
	}
	cout<<res<<endl;
	return 0;
}

编程题

杨辉三角
//ac代码
#include<bits/stdc++.h>
using namespace std;
//因为不能二维数组不能定义太大,不然运行有问题,这里用到了剪枝,所以数组列数大胆的设置为40 
int a[1000010][40];

signed main()
{
	int n;
	cin>>n;
	if(n==1){
		cout<<1<<endl;
		return 0;
	}
	long long res=0;
	a[1][0]=1;
	a[1][1]=1;
	for(int i=2;i<1000010;i++){
		a[i][0]=1;
		for(int j=1;j<=i;j++){
			a[i][j]=a[i-1][j-1]+a[i-1][j];
			if(a[i][j]==n){
				for(int k=1;k<=i;k++) res+=k;
				res+=j;
				res++;
				cout<<res<<endl;
				return 0;
			}
			//进行剪枝防止超出数组范围,同时降低复杂度
			//剪枝原理:int的数据存储范围差不多是1e9,与题目相符
			//所以如果当前相加数字等于负数,就说明此时数字超出了int范围,后面的数据也没有求的必要
			//就进行剪枝,break,这样既节省了空间也节省时间 
			if(a[i][j] < 0) break;
		}
	}
	//如果在上述循环至100010的过程中,还没有找到n
	//杨辉三角基本到5万行左右的数据就会大于1e9了,如果还没出现过,那么其出现的位置
	//不可能在中间位置,只有可能在第n+1行,第2个数字出现 
	//这个规律可以在多写几行杨辉三角后总结 
	cout << (long long)n * (n + 1) /2 + 2 << endl;
	return 0;
}
时间显示
//ac代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int dayms=86400000;
const int hms=3600000;
const int mms=60000;
const int sms=1000;
//快读
inline int read()
{
    
    
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
    
    
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
    
    
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
//快写
inline void write(int x)
{
    
    
    if(x<0){
    
    
    	putchar('-');
		x=-x;
	}
    if(x>9) 
		write(x/10);
    putchar(x%10+'0');
}

signed main()
{
    
    
	//int cintime = read();
	int cintime;
	cin>>cintime;
	cintime%=dayms;
	int t[3];
	if(cintime>=hms){
    
    
		t[0]=cintime/hms;
		cintime%=hms;
	}else t[0]=0;
	if(cintime>=mms){
    
    
		t[1]=cintime/mms;
		cintime%=mms;
	}else t[1]=0;
	if(cintime>=sms){
    
    
		t[2]=cintime/sms;
		cintime%=sms;
	}else t[2]=0;
	for(int i=0;i<2;i++){
    
    
		if(t[i]>=0&&t[i]<=9) printf("0%d:",t[i]);
		else printf("%d:",t[i]);
	}
	if(t[2]>=0&&t[2]<=9) printf("0%d\n",t[2]);
	else printf("%d\n",t[2]);
	return 0;
} 
双向排序(60分)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000;
const int maxm = 100000;
int n,m;
int a[maxn];

bool cmp(const int a,const int b){
    
    
	return a>b;
}

int main()
{
    
    
	cin>>n>>m;
	for(int i=1;i<=n;i++) a[i]=i;
	bool issort=false;//刚开始的数组的升序的,那么如果开始的p是1,就不需要sort,节约时间 
	while(m--){
    
    
		int p,q;
		cin>>p>>q;
		if(p==0) issort=true; 
		if(p==0&&issort==true) sort(a+1,a+q+1,cmp);
		else if(p==1&&issort==true) sort(a+q,a+n+1);
	}
	for(int i=1;i<=n;i++) cout<<a[i]<<" ";
	cout<<endl;
	return 0;
}

砝码称重

题意:
有n个砝码,可以放在天平两端,问有多少种可能的结果

输入样例:
3
1 4 6
输出样例:
10

样例解释:
能称出的 10 种重量是:1、2、3、4、5、6、7、9、10、11。
1 = 1;
2 = 6 − 4 (天平一边放 6,另一边放 4);
3 = 4 − 1;
4 = 4;
5 = 6 − 1;
6 = 6;
7 = 1 + 6;
9 = 4 + 6 − 1;
10 = 4 + 6;
11 = 1 + 4 + 6

解题思路:
看了很多篇题解,用dp动态背包解,dp[i][j]存储 前i个砝码能否得出j重量的结果,举例说明一下:
我们已知前0个砝码肯定能得到重量为0,所以dp[0][0]=true,那么第一个遍历的砝码我们假设w[1]=2,那么前1个砝码可以得到的重量,就有三种可能:
第一种就是0。因为前0个砝码可以为0,那么前1个砝码必然可以;即dp[1][0]=true;
第二种情况就是0+w[1]=2。这个不需要多解释,上一次重量基础上加上这次的重量;即dp[1][2]=true;
第三种情况就是|0-w[i]|=2。因为砝码可以放在天平两端,所以做减法,又因为求的是重量结果,没有负数,所以是绝对值;即dp[1][2]=true;

上面的过程相当于就是在修改i=1时的dp[1][j]状态,那么我们就可以,遍历1-n个砝码,重复上述过程,依次修改状态。
那么dp状态方程,就是将上述过程反推一下
dp[i][j]= dp[i-1][j] | dp[i-1][j+w[i]] | dp[i-1][abs(j-w[i])]

最后遍历dp[n]一列中有多少为true即可

//ac代码
#include<bits/stdc++.h>
using namespace std;
int w[110];
bool dp[105][1000001];//储存前i个能否得到j的重量的可行性 

int main()
{
    
    
	int n;
	cin>>n;
	int sum=0;
	for(int i=1;i<=n;i++){
    
    
		cin>>w[i];
		sum+=w[i];//可能得到的最大的重量就是总和 
	}
	
	//开始从0开始修改状态
	dp[0][0]=true;//前0个砝码肯定可以得到重量0
	for(int i=1;i<=n;i++){
    
    
		dp[i][0]=true;
		for(int j=1;j<=sum;j++){
    
    
			//三种某一种成立均可 
//			dp[i][j]=dp[i-1][j];//第一种情况,如果前i-1砝码可以得到j,那么前i个肯定也可以
//			dp[i][j]=dp[i-1][j+w[i]];//第二种情况,相加
//			dp[i][j]=dp[i-1][abs(j-w[i])];//第三种情况,相减 
            dp[i][j]=dp[i-1][j] | dp[i-1][j+w[i]] | dp[i-1][abs(j-w[i])];
		}
	} 
	
	int res=0;
	for(int i=1;i<=sum;i++){
    
    
		if(dp[n][i] == true) {
    
    
			//cout<<i<<endl;
			res++;
		}
	}
	cout<<res<<endl;
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/Charon_x/article/details/124044050