CF725模拟赛补题报告(Div.3)

提示:没写第五题,有点小难

文章目录

一、比赛分数

A,B,C,F题AC,D题对了一个测试点,其余没有考虑

二、比赛过程

先考虑A题,虽然简单,但也难了我几分钟,B题很轻松,到了C题就上难度了,虽然知道是二分但一点也不好写,但至少也写出来了,D题没思路就看了F题,发现特别水就A了,最后D题想到了方法但因为低级错误没有及时A掉,只对了一点(60分之1)。


三、解题报告

1.石头游戏

情况:赛中AC

题意:已知一个长度为 n 的整数序列,每次都只能删掉最左或最右的一个数字,求最少多少次,可以把最小值和最大值都删掉。

题解方法:分三种方法讨论,从两头找,从左边找,从右边找,输出最小值。

题解代码:

#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define CLOSE std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define N 1000005
#define M 100005
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
using namespace std;
ll a[N],maxx=-inf,minn=inf,cnt1,cnt2,cnt3;
int main(){	
	CLOSE;
	ll t;
	cin>>t;
	while(t--){
		ll n;
		cin>>n;
		maxx=-inf,minn=inf;
		cnt1=0,cnt2=0,cnt3=0;
		if(n==1){
			cout<<1<<endl;
			continue;
		}
		for(int i=1;i<=n;i++){
			cin>>a[i];
			maxx=max(maxx,a[i]);
			minn=min(minn,a[i]);
		}
		for(int i=1;i<=n;i++){
			cnt1++;
			if(a[i]==maxx||a[i]==minn){
				break;
			}
		}
		for(int i=n;i>=1;i--){
			cnt1++;
			if(a[i]==maxx||a[i]==minn){
				break;
			}
		}
		ll flag1=0,flag2=0;
		for(int i=1;i<=n;i++){	
			cnt2++;
			if(a[i]==maxx){
				flag1=1;
			}
			if(a[i]==minn){
				flag2=1;
			}
			if(flag1==1&&flag2==1){
				break;
			}
		}
		flag1=0,flag2=0;
		for(int i=n;i>=1;i--){
			cnt3++;
			if(a[i]==maxx){
				flag1=1;
			}
			if(a[i]==minn){
				flag2=1;
			}
			if(flag1==1&&flag2==1){
				break;
			}
			
		}
//		cout<<cnt1<<" "<<cnt2<<" "<<cnt3<<endl; 
		cout<<min(cnt1,min(cnt2,cnt3))<<endl;
	}
	return 0;
}

2.朋友与糖果

情况:赛中AC

题意:已知一个长度为 n 的整数序列,第 i 个整数表示第 i 个朋友的糖果数,从中选 k 个整数,这些整数的总糖果数可以重新分配到 n 个数字中,使得n个数字全部相同。求最小的 k 。

题解方法:选出来重新分配的糖果数肯定有最大的数字,还要知道平均值是多少,这是分配的目标,那么超过这个平均值的,都是我们应该选出来重新分配的。

题解代码:

#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define CLOSE std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define N 1000005
#define M 100005
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
using namespace std;
ll t,n,a[N];
int main(){
	CLOSE;
	cin>>t;
	while(t--){
		cin>>n;
		ll sum=0,k=0;
		for(int i=1;i<=n;i++){
			cin>>a[i]; 
			sum+=a[i];
		}
		if(sum%n!=0){ 
			cout<<-1<<endl;
			continue;
		}
		sum/=n;
		for(int i=1;i<=n;i++){
			if(sum<a[i]){
				k++;
			}
		}
		cout<<k<<endl;
	}
	return 0;
}

3.符合要求的对数

情况:赛中AC

题意:给一个数组,求有多少对元素相加结果在 [l,r] 之间。

题解方法:先排序,可以采取二分的方法,在固定一个数后进行二分,找到符合要求的最大数和最小数,如过符合要求,累加下标的差。

题解代码:

#include<bits/stdc++.h>
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define isd(c) ('0' <= (c) && (c) <= '9')
#define isa(c) ('a' <= (c) && (c) <= 'z')
#define isA(c) ('A' <= (c) && (c) <= 'Z')
#define mem(a, b) memset(a, b, sizeof a);
#define N 1000005
#define M 2000005
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PI acos(-1)
#define endl "\n"
#define pii pair<long long,long long>
#define F first
#define S second
#define bug cout << endl << " .....here!...." << endl;
// #pragma GCC optimize("O3")
//#define Time (double)clock() / CLOCKS_PER_SEC <= 0.95
//using namespace __gnu_cxx;
//using namespace __gnu_pbds;
using namespace std;
ll a[N], cnt;
int main() {
	CLOSE;
	ll t;
	cin >> t;
	while (t--) {
		ll n, l, r;
		cin >> n >> l >> r;
		cnt = 0;
		for (int i = 1; i <= n; i++) {
			cin >> a[i];
		}
		sort(a + 1, a + 1 + n);
		for (int i = 1; i <= n; i++) {
			ll x = a[i];
			ll y = lower_bound(a+i+1,a+n+1,l-a[i])-a;
			ll z=upper_bound(a+i+1,a+n+1,r-a[i])-a;
			z--;
			if(y>z){
				continue;
			}
			else{
				cnt+=z-y+1;
			}
		}
		cout << cnt << endl;
	}
	return 0;
}

4.除法问题

情况:赛中A了1个测试点,补题正确。

题意:给我们两个整数 a 和 b,判断能否恰好 k 步除法运算(每次都要整除)使得两数相等。

题解方法:我们可以先求出a和b变成相同的最多除多少步,显然是都变成1,每次除素因子,步数最多,所以统计a 和 b 的素因子个数即可,a最多ak步,b最多bk步,总共最多ak + bk 步。
要想再少的步数,可以多个素因子凑一个合数除法运算,但是想要再多的步数 ( > ak+bk) 就不可以了。比较特殊的是当k==1,不能直接和 ak + bk 比较,因为k是1,只能对其中一个数除法,另一个数不能变,那就表示必须有倍数关系,且不相同。
注意:这里能用 int 就不用 long long 了,防止时间超限!!!!!

题解代码:

#include<bits/stdc++.h>
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define isd(c) ('0' <= (c) && (c) <= '9')
#define isa(c) ('a' <= (c) && (c) <= 'z')
#define isA(c) ('A' <= (c) && (c) <= 'Z')
#define mem(a, b) memset(a, b, sizeof a);
#define N 1000005
#define M 2000005
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PI acos(-1)
#define endl "\n"
#define pii pair<long long,long long>
#define F first
#define S second
#define bug cout << endl << " .....here!...." << endl;
#pragma GCC optimize("O3")
//#define Time (double)clock() / CLOCKS_PER_SEC <= 0.95
//using namespace __gnu_cxx;
//using namespace __gnu_pbds;
using namespace std;
int cnt,w1=0,w2=0,cnt1,cnt2,base1[N],base2[N];
void fen1(int n){
	w1=0;
	for(int i=2;i*i<=n;i++){
		if(n%i==0){
			n=n/i;
			w1++;
			while(n%i==0){
				n=n/i;
				w1++;
			}
		}
	}
	if(n>1){
		w1++;
	}
}
void fen2(int n){
	w2=0;
	for(int i=2;i*i<=n;i++){
		if(n%i==0){
			n=n/i;
			w2++;
			while(n%i==0){
				n=n/i;
				w2++;
			}
		}
	}
	if(n>1){
		w2++;
	}
}
int main() {
	CLOSE;
	int t;
	cin>>t;
	while (t--) {
		int a,b,k;
		cin>>a>>b>>k;
		if(k==1){
			if(a==b){
				cout<<"NO"<<endl;
				continue;
			}
			if(max(a,b)%min(a,b)==0){
				cout<<"YES"<<endl;
				continue;
			}
			else{
				cout<<"NO"<<endl;
				continue;
			}
		}
		fen1(a);
		fen2(b);
		if(w1+w2>=k){
			cout<<"YES"<<endl;
			continue;
		} 
		else{
			cout<<"NO"<<endl;
			continue;
		}
	}
	return 0;
}

5.有趣的加法

情况:赛中AC

题意:给我们两个整数 a 和 b,判断能否恰好 k 步除法运算(每次都要整除)使得两数相等。

题解方法:变化1位的次数就是b-a,变化两位就是这两个除以10再作差,以此类推。

题解代码:

#include<bits/stdc++.h>
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define isd(c) ('0' <= (c) && (c) <= '9')
#define isa(c) ('a' <= (c) && (c) <= 'z')
#define isA(c) ('A' <= (c) && (c) <= 'Z')
#define mem(a, b) memset(a, b, sizeof a);
#define N 1000005
#define M 2000005
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PI acos(-1)
#define endl "\n"
#define pii pair<long long,long long>
#define F first
#define S second
#define bug cout << endl << " .....here!...." << endl;
//#pragma GCC optimize("O3")
//#define Time (double)clock() / CLOCKS_PER_SEC <= 0.95
//using namespace __gnu_cxx;
//using namespace __gnu_pbds;
using namespace std;
ll cnt;
int main() {
	CLOSE;
	ll t;
	cin>>t;
	while (t--) {
		ll l,r;
		cin>>l>>r;
		cnt=0;
		while(r){
			cnt+=(r-l);
			r/=10;
			l/=10;
		}
		cout<<cnt<<endl;
	}
	return 0;
}

6.礼品套装

情况:补题正确

题意:已知四个整数 x,y,a 和 b分别表示一共有x颗红色糖果和y颗蓝色糖果,一个礼品套装可以是a
粒红色糖果和b粒蓝色糖果,或者a粒蓝色糖果和b粒红色糖果。也就是x,y按照a,b还是按照b,a分,可以使得分的组数最大,求最大组数。

题解方法:

题解代码:

#include<bits/stdc++.h>
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define isd(c) ('0' <= (c) && (c) <= '9')
#define isa(c) ('a' <= (c) && (c) <= 'z')
#define isA(c) ('A' <= (c) && (c) <= 'Z')
#define mem(a, b) memset(a, b, sizeof a);
#define N 1000005
#define M 2000005
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PI acos(-1)
#define endl "\n"
#define pii pair<long long,long long>
#define F first
#define S second
#define bug cout << endl << " .....here!...." << endl;
#pragma GCC optimize("O3")
//#define Time (double)clock() / CLOCKS_PER_SEC <= 0.95
//using namespace __gnu_cxx;
//using namespace __gnu_pbds;
using namespace std;
ll x,y,a,b;
bool check(ll mid){
	ll l=ceil((1.0*(x-b*mid)/(a-b)));
	ll r=floor((1.0*(y-a*mid)/(b-a)));
	l=max(l,(ll)0);
	r=min(r,mid);
	return l<=r;
}
void solve(){
	cin>>x>>y>>a>>b;
	if(a==b){
		cout<<min(x/a,y/a)<<endl;
		return ;
	}
	if(x>y){
		swap(x,y);
	}
	if(a>b){
		swap(a,b);
	}
	ll l=0,r=y;
	while(l<r){
		ll mid=(l+r+1)/2;
		if(check(mid)){
			l=mid;
		}
		else{
			r=mid-1;
		}
	}
	cout<<r<<endl;
}
int main() {
	CLOSE;
	ll t;
	cin>>t;
	while (t--) {
		solve();
	}
	return 0;
}

四、赛事总结

1.注意一些细节的错误,例如变量用错了,头文件没写,手滑吧l打成1了等。

2.活跃思路,灵活运用方法,掌握做题策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值