CF1538补题报告(A.B.C.D.F.G.)
Codeforces Round 725 (Div. 3)
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. 朋友与糖果
给定一个序列代表每人的糖果数量,每次操作可以将一个人的部分糖果分给另一个人,求使每个人所有的糖果均等需进行多少次操作
求出平均值,并判断是否为整数,非整数直接输出-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. 对数
给定一个序列和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. 关于除法的另一个问题
给定两个整数以及操作数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. 有趣的函数
给定两个正整数,使第一个数不断加一,一直加到第二个数,求出此过程中变化的位数的总数
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. 礼品套装
给定有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;
}