CF1538 补题报告

CF1538补题报告(A.B.C.D.F.G.)
Codeforces Round 725 (Div. 3)

A. Stone Game

A. 石头游戏

题意

给定一个序列,每次只能删除最左边或最右边的元素,求出删除最大和最小值需要多少次删除操作。

思路

找到最大值和最小值所在的位置,取四种情况中的最小值。

代码

#include
using namespace std;
int n,a[105],t,maxn=1,minna=1;
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			
		}
		maxn=1,minna=1;
		for(int i=2;i<=n;i++){
			if(a[i]>a[maxn]){
				maxn=i;
			}
			if(a[i]<a[minna]){
				minna=i;
			}
		}
		cout<<min((maxn+n-minna+1),min((minna+n-maxn+1),min(max(maxn,minna),max(n-maxn+1,n-minna+1))))<<endl;
	}
	return 0;
}

B. Friends and Candies

B. 朋友与糖果

题意

给定一个序列代表每人的糖果数量,每次操作可以将一个人的部分糖果分给另一个人,求使每个人所有的糖果均等需进行多少次操作

思路

求出平均值,并判断是否为整数,非整数直接输出-1,因为分配糖果都是从糖果多的人分给糖果少的人,所以统计有多少人的糖果大于平均值

代码

#include
using namespace std;
int t,n,a[200005],b,sum;
bool fl;
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		b=0,fl=0,sum=0;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			b+=a[i];
			if(i>1&&a[i]!=a[i-1]){
				fl=1;
			}
		}
		if(b%n!=0){
			printf("-1\n");
			continue;
		}
		if(!fl){
			printf("0\n");
			continue;
		}
		b/=n;
		for(int i=1;i<=n;i++){
			if(b<a[i]){
				sum++;
			}
		}
		printf("%d\n",sum);
	} 
	return 0;
}

C. Number of Pairs

C. 对数

题意

给定一个序列和l,r,求在序列中有多少对数的和在[l,r]这个区间内

思路

首先将此序列排序,然后遍历数对的第一个数,二分查找第二个数的区间,输出所有区间的和

代码

#include
using namespace std;
long long t,n,a[200005],b,sum,l,r,la,ra;
bool fl;
int main(){
	cin>>t;
	while(t--){
		cin>>n>>l>>r;
		for(int i=1;i<=n;i++){
			cin>>a[i];
		}
		sort(a+1,a+n+1);
		sum=0;
		for(int i=1;i<=n;i++){
			sum+=upper_bound(a+1+i,a+n+1,r-a[i])-lower_bound(a+1+i,a+n+1,l-a[i]);
		}
		
		printf("%lld\n",sum);
	} 
	return 0;
} 

D. Another Problem About Dividing Numbers

D. 关于除法的另一个问题

题意

给定两个整数以及操作数k,每次操作可以使a或b除以一个数,问是否可以在除以一个数k次操作后使得a=b

思路

质因数之和即操作的最大值,所以此题只需求二数的质因数个数之和是否大于k即可,但是如果a、b不成倍数关系且k=1,输出NO

代码

#include
using namespace std;
long long ans,t,a,b,k;
int fenjie(int a){
	int sum=0;
	for(int i=2;i*i<=a;i++){
		while(a%i==0){
			a/=i;
			sum++;
		}
	}
	if(a>1){
		sum++;
	}
	return sum;
}
int main(){
	cin>>t;
	while(t--){
		cin>>a>>b>>k;
		int ka=fenjie(a),kb=fenjie(b);
		if(k==1){
			if((a%b==0||b%a==0)&&a!=b){
				printf("YES\n");
			}
			else{
				printf("NO\n");
			}
		}
		else{
			if(ka+kb>=k){
				printf("YES\n");
			}
			else{
				printf("NO\n");
			}
		}
		
	}
	return 0;
}

F. Interesting Function

F. 有趣的函数

题意

给定两个正整数,使第一个数不断加一,一直加到第二个数,求出此过程中变化的位数的总数

思路

l,r每次去掉个位,遍历所有位,求r-l的总和

代码

#include
using namespace std;
long long ans,t,a,b;
int main(){
	cin>>t;
	while(t--){
		cin>>b>>a;
		ans=0;
		while(a!=0){
			ans+=a-b;
			a/=10,b/=10;
		}
		printf("%lld\n",ans);
	} 
	return 0;
}

G. Gift Set

G. 礼品套装

题意

给定有x个红糖,y个蓝糖,由它们组成多个礼品盒,要求每个礼品盒内必须要有a个红糖b个蓝糖或者是a个蓝糖b个红糖,问最多能组成多少个礼品盒

思路

利用二分查找, m i d mid mid 为礼品盒数,其中要保证红糖数量的最大值不小于蓝糖数量的最小值

代码

#include
using namespace std;
long long t,x,y,a,b;
bool check(int mid){
	int l=ceil(1.0*(x-b*mid)/(a-b));
	int r=floor(1.0*(y-a*mid)/(b-a));
	l=max(l,0);
	r=min(mid,r);
	return l<=r;
}
int main(){
	cin>>t;
	while(t--){
		cin>>x>>y>>a>>b;
		if(a==b){
			printf("%lld\n",min(x/a,y/a));
			continue;
		}
		if(x>y){
			swap(x,y);
		}
		if(a>b){
			swap(a,b);
		}
		int l=0,r=y;
		while(l<r){
			int mid=(l+r+1)/2;
			if(check(mid)){
				l=mid;
			}
			else{
				r=mid-1;
			}
		}
		printf("%lld\n",l);
	}
	return 0;
}

你可能感兴趣的:(c++,笔记)