第十二届蓝桥杯省赛第二场C++B组真题

第十二届蓝桥杯省赛第二场C++B组真题

P3496. 特殊年份

题目:特殊年份
思路:

模拟即可

代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int x;
int cnt;
bool check(int x){
	int a=x%10;//个位
	int b=(x/10)%10;//十位
	int c=(x/100)%10;//百位
	int d=x/1000;//千位
	if((b==d)&&(a-c==1)) return true;
	return false;
}
int main(){
	while(cin>>x){
		if(check(x)) cnt++;
	}
	printf("%d\n",cnt);
	return 0;
} 

P3490. 小平方

题目:小平方
思路:

模拟即可

代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,x;
int cnt;
bool check(int x){
	int cmp;
	if(n%2==0) cmp=n/2;
	else cmp=n/2+1;
	if((x*x)%n<cmp) return true;
	return false;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		if(check(i)) cnt++;
	}
	printf("%d\n",cnt);
	return 0;
} 

P3491. 完全平方数

题目:完全平方数
思路:

分解质因数即可,如果一个质因数个数是奇数就再乘一个

代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
int main(){
	LL x;
	scanf("%lld",&x);
	LL res=1;
	for(int i=2;i<=x/i;i++){ 
		if(x%i==0){
			int s=0;
			while(x%i==0){
				x/=i;
				s++;
			}
			if(s%2!=0) res*=i;
		}
	}
	if(x>1) res*=x; 
	printf("%lld",res);
	return 0;
} 

P3492. 负载均衡

题目:负载均衡
思路:

时间复杂度要做到O(nlogn),对于每一个计算机,我们用一个小根堆来维护它正在执行的所有任务
负载均衡
对于每个任务来说,先把结束时间在起点之前的任务全部删掉,这其实就是一个找到最小值删除最小值的过程,可以用小根堆

代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N=2e5+10;
int n,m;
int s[N];//每个计算机剩余的算力 
priority_queue<PII,vector<PII>,greater<PII>> q[N];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&s[i]);
	while(m--){
		int a,b,c,d;
		scanf("%d%d%d%d",&a,&b,&c,&d);
		while(q[b].size()&&q[b].top().x<=a){
			s[b]+=q[b].top().y;
			q[b].pop();
		}
		if(s[b]>=d){
			q[b].push({a+c,d});
			s[b]-=d;
			printf("%d\n",s[b]);
		}
		else puts("-1");
	}
	return 0;
}

P3494. 国际象棋

题目:国际象棋
思路:

状态压缩DP,P1064 小国王+P292 炮兵阵地 的结合版
状态表示:
集合: f[i][a][b][j]表示前i列已经摆好,并且第i-1列状态是a,第i列状态是b,一共放置了j个皇后的所有方案
属性: cnt(数量)
状态计算:
闫氏DP
不用行而用列的原因:列最多为100,如果用行,意味着状态数最多为 2 100 2^{100} 2100,但行数最多是6,那么如果用列状态数最多是 2 6 2^6 26
状态定义顺序可以随便,比如说f[i][j][a][b]也能做,只要保证用来更新的状态在当前状态之前被算出来即可

代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=110,M=1<<6,K=21,mod=1e9+7;
int n,m,k;
int f[N][M][M][K];
int get_count(int x){//统计x中1的个数 
	int res=0;
	while(x){
		res++;
		x-=(x&-x);
	}
	return res;
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	f[0][0][0][0]=1;//一开始棋盘上啥都没有 
	for(int i=1;i<=m+2;i++){//第1列到第m+2列
		for(int a=0;a<1<<n;a++){
			for(int b=0;b<1<<n;b++){
				if(b&(a<<2)||b&(a>>2)) continue;//能相互攻击到
				int t=get_count(b);
				for(int c=0;c<1<<n;c++){
					if(a&(c<<2)||a&(c>>2)) continue;
					if(b&(c<<1)||b&(c>>1)) continue;
					for(int j=t;j<=k;j++){
						f[i][a][b][j]=(f[i][a][b][j]+f[i-1][c][a][j-t])%mod;
					}
				} 
			}
		}
	}
	printf("%d\n",f[m+2][0][0][k]);//小技巧,这样就不用枚举f[m][i][j][k]了
	return 0;
}

滚动数组优化:
一样的套路,可以把第一维优化到2,但会多一层循环来清空数组

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int M=1<<6,K=21,mod=1e9+7;
int n,m,k;
int f[2][M][M][K];
int get_count(int x){//统计x中1的个数 
	int res=0;
	while(x){
		res++;
		x-=(x&-x);
	}
	return res;
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	f[0][0][0][0]=1;//一开始棋盘上啥都没有 
	for(int i=1;i<=m+2;i++){//第1列到第m+2列
		for(int a=0;a<1<<n;a++){
			for(int b=0;b<1<<n;b++){
				if(b&(a<<2)||b&(a>>2)) continue;//能相互攻击到
				int t=get_count(b);
				for(int j=t;j<=k;j++) f[i&1][a][b][j]=0;//要先清空滚动数组
				for(int c=0;c<1<<n;c++){
					if(a&(c<<2)||a&(c>>2)) continue;
					if(b&(c<<1)||b&(c>>1)) continue;
					for(int j=t;j<=k;j++){
						f[i&1][a][b][j]=(f[i&1][a][b][j]+f[i-1&1][c][a][j-t])%mod;
					}
				} 
			}
		}
	}
	printf("%d\n",f[m+2&1][0][0][k]);//小技巧,这样就不用枚举f[m][i][j][k]了
	return 0;
}

差距:
滚动数组
优化

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值