HBCPC2020-第四届河北省大学生程序设计竞赛题解(部分)


7-1 须知

二、题解

1.基本思路:

  • 特判一下,其余都都输“05:05”

2.代码:

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

#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl '\n'
#define int long long
#define fi first
#define se second
typedef pair<int,int> PII;
const int N = 1e6+10, INF = 0x3f3f3f3f;


void solve(){
	int h,m;
	scanf("%lld:%lld",&h,&m);
	string s; cin>>s;
	if(s=="7-1"){
		m+=5;
		h+=m/60;
		m%=60;
		printf("%02lld:%02lld\n",h,m);
	}
	else cout<<"05:05"<<endl;
	
}

signed main(){
	int T=1;
//	IOS;
	cin>>T;
    while(T--){
    	solve();
	} 
	return 0;
}
/*

*/

7-5 删点

二、题解

1.基本思路:

  • 可以发现,总的方案数就是图的每个连通块的方案数之积
  • 为什么是之积呢?因为不同的连通块之间也可以构成一种方案
  • 那么每个连通块的方案数该怎么算呢?不难发现,每个连通块就方案数就是C(x,1)+C(x,2)+C(x, x-1),其中C(x, x)不满足删点条件,如果遍历累加的话,会超时
  • 可以用组合公式,2^x-1,算上空集的话
  • 当然求连通块可以用并查集或dfs都可以

2.代码:

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

#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl '\n'
#define int long long
#define fi first
#define se second
typedef pair<int,int> PII;
const int N = 1e6+10, INF = 0x3f3f3f3f;
const int mod = 998244353;
int n,m,ans=1;
int fa[N],siz[N];
vector<int> res;

int find(int x){
	return x==fa[x]?x:fa[x]=find(fa[x]);
}

int qpow(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=res*a%mod;
		b>>=1;
		a=a*a%mod;
	}
	return res;
}

void solve(){
	cin>>n>>m;
	for( int i=1;i<=n;i++) fa[i]=i,siz[i]=1;
	for(int i=1;i<=m;i++){
		int a,b; cin>>a>>b;
		int x=find(a),y=find(b);
		if(x!=y){
			fa[x]=y;
			siz[y]+=siz[x];
		}
	}
	set<int> s;
	for(int i=1;i<=n;i++){
		int x=find(i);
		if(s.count(x)) continue;
		s.insert(x);
		res.push_back(siz[x]);
	} 
	for(auto i:res){
		ans=(ans*(qpow(2,i)%mod-1+mod))%mod;
	}
	cout<<ans;
}

signed main(){
	int T=1;
//	IOS;
//	cin>>T;
    while(T--){
    	solve();
	} 
	return 0;
}
/*

*/

7-7 划分

二、题解

1.基本思路:

  • n的数据范围是5e3,时间复杂度O(n^2)也是可以的
  • 需要用前缀和预处理一下
  • 然后dp求最大个数

2.代码:

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

#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl '\n'
#define int long long
#define fi first
#define se second
typedef pair<int,int> PII;
const int N = 5e3+10, INF = 0x3f3f3f3f;
int n,l,r;
int a[N],sum[N];
int dp[N];


void solve(){
	cin>>n>>l>>r;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum[i]=+sum[i-1]+a[i];
	}
	for(int i=1;i<=n;i++){
		dp[i]=dp[i-1]; //不选当前的数
		for(int j=1;j<=i;j++){ //区间范围[j,i]
			int x=sum[i]-sum[j-1];
			if(x>=l&&x<=r)
			  dp[i]=max(dp[i],dp[j-1]+1);
		}
	}
//	for(int i=1;i<=n;i++) cout<<dp[i]<<' ';
    cout<<dp[n]<<endl;
}

signed main(){
	int T=1;
	IOS;
	cin>>T;
    while(T--){
    	solve();
	} 
	return 0;
}
/*

*/

7-10 奖牌

二、题解

1.基本思路:

  • 签到题

2.代码:

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

#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl '\n'
#define int long long
#define fi first
#define se second
typedef pair<int,int> PII;
const int N = 1e6+10, INF = 0x3f3f3f3f;


void solve(){
	string s; cin>>s;
	map<string,string> mp;
	mp["gold"]="Au";
	mp["silver"]="Ag";
	mp["bronze"]="Cu";
	cout<<mp[s];
}

signed main(){
	int T=1;
//	IOS;
//	cin>>T;
    while(T--){
    	solve();
	} 
	return 0;
}
/*

*/

7-12 挤牙膏

二、题解

1.基本思路:

  • 按照题意模拟,直接遍历?
  • 不知道有没有O(1)的复杂度,直接算法出来?

2.代码:

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

#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl '\n'
#define int long long
#define fi first
#define se second
typedef pair<int,int> PII;
const int N = 1e6+10, INF = 0x3f3f3f3f;


void solve(){
	int m,c1,c2;
	cin>>m>>c1>>c2;
	vector<int> f1(m+1),f2(m+1);
	for(int i=1;i<=m;i++) cin>>f1[i]>>f2[i];
	int sum1=0,sum2=0;
	for(int i=1;i<=m;i++){
		int t1=min(c1,(int)(c1*f1[i]*1.0/1e9));
		sum1+=t1; c1-=t1;
		
		int t2=min(c2,(int)(c2*f2[i]*1.0/1e9));
		sum2+=t2; c2-=t2;
	}
	cout<<(sum1>sum2?"Rilly":"Northy")<<endl;
}

signed main(){
	int T=1;
	IOS;
	cin>>T;
    while(T--){
    	solve();
	} 
	return 0;
}
/*

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值