Codeforces Round #540 (Div. 3)

61 篇文章 0 订阅

A链接
讨论一下 2 a 2a 2a b b b的大小关系即可。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <bitset>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define MAXN 1010100
#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll __int64
#define INF 0x7fffffff
#define cs(s) freopen(s,"r",stdin)
#define mem(x) memset(x,0,sizeof(x))
#define PI acos(-1)
#define eps 1e-10
using namespace std;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
//head
int main(){
	ios::sync_with_stdio(false);
	int t;
	for(cin>>t;t;t--){
		LL n,a,b;
		cin>>n>>a>>b;
		if(2*a<=b)cout<<1ll*n*a<<endl;
		else {
			cout<<(1ll*n/2*b+1ll*(n%2)*a)<<endl;
		}

	}
	return 0;
}

B链接
分奇偶性,预处理前缀和,然后遍历每个位置,判断一下即可。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <bitset>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define MAXN 1010100
#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll __int64
#define INF 0x7fffffff
#define cs(s) freopen(s,"r",stdin)
#define mem(x) memset(x,0,sizeof(x))
#define PI acos(-1)
#define eps 1e-10
using namespace std;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
//head
LL sum[200001],sumA[200001][2],sumB[200001],a[200001];
int main(){
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i],sum[i]=sum[i-1]+a[i];
	sum[1]=a[1];
	for(int i=1;i<=n;i++){
		if(i%2)sumA[i][1]=sumA[i-1][1]+a[i],sumA[i][0]=sumA[i-1][0];
		else sumA[i][0]=sumA[i-1][0]+a[i],sumA[i][1]=sumA[i-1][1];
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		if(sumA[i-1][0]+sumA[n][1]-sumA[i][1]==sumA[i-1][1]+sumA[n][0]-sumA[i][0])ans++;
	}
	cout<<ans<<endl;
	return 0;
}

C链接
模拟,题意是判断给的 n 2 n^2 n2个数能否组成一个回文矩阵。
分奇偶讨论:
n为偶数时,每个位置与之对称的位置有四个,即判断是否有一个数出现次数大于四,遍历 1 4 \frac{1}{4} 41矩阵的每个位置即可。
n为奇数时,奇数与偶数不同的地方在于,必然有且仅有一个数出现了奇数次,这个数放正中间,然后遍历有四个对称位置的位置,放出现大于四次的即可,然后,中间行和中间列的每个元素与之对称的位置有两个,找出现大于两次的放即可。
若中间放的过程中,找不到满足的即输出-1。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <bitset>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define MAXN 1010100
#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll __int64
#define INF 0x7fffffff
#define cs(s) freopen(s,"r",stdin)
#define mem(x) memset(x,0,sizeof(x))
#define PI acos(-1)
#define eps 1e-10
using namespace std;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
//head
int a[444],cnt[1111];
int ans[22][22];
int main(){
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	for(int i=1;i<=n*n;i++)cin>>a[i],cnt[a[i]]++;
	if(n==1){cout<<"YES\n"<<a[1];return 0;}
	if((n)%2){
		int bj=0;
		for(int k=1;k<=1000;k++){
			if(cnt[k]%2!=0){ans[(n+1)/2][(n+1)/2]=k,bj=1;cnt[k]--;break;}
		}
		if(!bj)return cout<<"NO\n",0;
	}
	for(int i=1;i<=1000;i++){
		if(cnt[i]%2)return cout<<"NO",0;
	}
	for(int i=1;i<=n/2;i++){
		for(int j=1;j<=n/2;j++){
			if(ans[i][j])continue;
			int bj=0;	
			for(int k=1;k<=1000;k++){
				if(cnt[k]>=4){
					ans[i][j]=k;
					ans[n-i+1][j]=k;
					ans[i][n-j+1]=k;
					ans[n-i+1][n-j+1]=k;
					cnt[k]-=4;
					bj=1;
					break;
				}
			}
			if(!bj){return cout<<"NO",0;}
		}
	}	
	if(n%2){
		for(int j=1;j<=n/2;j++){
			int bj=0;
			for(int i=1;i<=1000;i++){
				if(cnt[i]>=2){ans[j][(n+1)/2]=ans[n-j+1][(n+1)/2]=i,cnt[i]-=2;bj=1;break;}
			}
			if(!bj)return cout<<"NO",0;
		}
		for(int j=1;j<=n/2;j++){
			int bj=0;
			for(int i=1;i<=1000;i++){
				if(cnt[i]>=2){ans[(n+1)/2][j]=ans[(n+1)/2][n-j+1]=i,cnt[i]-=2;bj=1;break;}
			}
			if(!bj)return cout<<"NO",0;
		}
	}
	cout<<"YES\n";
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)cout<<ans[i][j]<<' ';
		cout<<endl;
	}
	return 0;
}

F1链接
题意是找到最多数量的边。
这种边满足:去掉这条边之后分成的两个部分,不同时存在红色和蓝色。
做法:两次dfs
第一次dfs:从1开始dfs这颗树,记录当前节点可以遍历到的红色,蓝色的数量。
第二次dfs:从1开始dfs这棵树,设当前节点为 u u u,下一个节点为 v v v,显然,从1到 v v v只能存在一个颜色,且另一个颜色只能存在于 v − &gt; n v-&gt;n v>n,记录下答案即可。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <bitset>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define MAXN 1010100
#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll __int64
#define INF 0x7fffffff
#define cs(s) freopen(s,"r",stdin)
#define mem(x) memset(x,0,sizeof(x))
#define PI acos(-1)
#define eps 1e-10
using namespace std;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
//head
const int N=3e5+11;
int n,a[N],ans;
vector<int>v[N];
int cnt[N][4];
void dfs1(int now,int pre){
	cnt[now][a[now]]++;
	for(auto k:v[now]){
		if(k==pre)continue;
		dfs1(k,now);
		for(int j=0;j<3;j++)cnt[now][j]+=cnt[k][j];
	}
}
void dfs2(int now,int pre){
	for(auto k:v[now]){
		if(k==pre)continue;
		dfs2(k,now);
		if(cnt[k][1]==0&&cnt[1][2]==cnt[k][2])ans++;
		if(cnt[k][2]==0&&cnt[1][1]==cnt[k][1])ans++;
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<n;i++){
		int s,t;
		cin>>s>>t;
		v[s].pb(t);
		v[t].pb(s);
	}
	dfs1(1,0);
	dfs2(1,0);
	cout<<ans<<endl;
	return 0;
}

D链接
题意是,有n杯咖啡,m页作业,每杯咖啡只能喝一次。每天可以喝任意多杯咖啡。
假如有一天喝了k杯咖啡,那么这一天的总贡献为 ∑ 1 k m a x ( a k i − k + 1 , 0 ) \sum_1^{k}max(a_{ki}-k+1,0) 1kmax(akik+1,0)
问 :最少要多少天能完成作业,或者完不成输出-1 。
做法:二分答案,上界n,下界1,ans初始为-1。
先将 n n n杯咖啡按权值排序(大的优先)
每次 c h e c k check check当前天数 m i d mid mid n n n杯咖啡均摊给 m i d mid mid天,依次递减,求出总贡献与m比较即可。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <bitset>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define MAXN 1010100
#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll __int64
#define INF 0x7fffffff
#define cs(s) freopen(s,"r",stdin)
#define mem(x) memset(x,0,sizeof(x))
#define PI acos(-1)
#define eps 1e-10
using namespace std;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
//head
LL n;
LL a[200001],ans=-1;
LL m;
int cmp(int A,int b){
	return A>b;
}
int ch(int k){
	int cnt=0;
	LL sum=0;
	int res=0;
	for(int i=1;i<=n;i++){
		sum+=max(a[i]-cnt,0ll);
		res++;
		if(res==k)cnt++,res=0;
	}
	return sum>=m;
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	LL sum=0;
	for(int i=1;i<=n;i++)cin>>a[i],sum+=a[i];
	if(sum<m)return cout<<-1,0;
	else if(sum==m)return cout<<n,0;
		sort(a+1,a+1+n,cmp);
	LL l=1,r=n;
	ans=-1;
	while(l<=r){
		LL mid=(l+r)/2;
		if(ch(mid))r=mid-1,ans=mid;
		else l=mid+1;
	}
	cout<<ans<<endl;	
	return 0;
}

E链接
题意:n对,k种颜色。
要求构造n对,满足:
(设每对的颜色为 g i , b i g_i,b_i gi,bi)
1.每一对的 g i ≠ b i g_i \neq b_i gi̸=bi
2. k ≤ g i , b i ≤ k k \leq g_i,b_i \leq k kgi,bik
3.不存在 i , j ( i ≠ j ) , b i = b j 且 g i = g j i,j(i \neq j),b_i=b_j且g_i=g_j i,j(i̸=j),bi=bjgi=gj
4. 1.... n − 1 满 足 b i ≠ b i + 1 , g i ≠ g i + 1 1....n-1满足b_i \neq b_{i+1},g_i \neq g_{i+1} 1....n1bi̸=bi+1,gi̸=gi+1
显然k种颜色最多可以构造 k ∗ ( k − 1 ) k*(k-1) k(k1)组不同的对。 n &gt; k ∗ ( k − 1 ) n&gt;k*(k-1) n>k(k1)则不可能构造出来,即输出-1。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <bitset>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define MAXN 1010100
#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll __int64
#define INF 0x7fffffff
#define cs(s) freopen(s,"r",stdin)
#define mem(x) memset(x,0,sizeof(x))
#define PI acos(-1)
#define eps 1e-10
using namespace std;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
//head
int a[200001];
int main(){
	ios::sync_with_stdio(false);
	int n,k;
	cin>>n>>k;
	if(n>1ll*k*(k-1))cout<<"NO\n";
	else{
		cout<<"YES\n";
		for(int i=1;i<=k;i++){
			a[i]=i+1;
			if(a[i]==k+1)a[i]=1;
		}
		for(int i=1,j=1;i<=n;i++){
			cout<<j<<' '<<a[j]<<endl;
			a[j]++;
			if(a[j]==k+1)a[j]=1;
			j++;
			if(j==k+1)j=1;
		}
	}
	return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值