cf--思维训练

发布于:2025-08-16 ⋅ 阅读:(13) ⋅ 点赞:(0)

B. MIN = GCD

题目来源
难度:1100

解题思路

我们可以想到,这个最小值一定只能是整个数组中的最小值,因为如果不是,那么左半部分的最小值是大于它的,如果它在右半部分,那么整体的GCD是一定不等于左半部分的最小值的。
所以可以对数组进行升序排序,而且右半部分的数必须是能整除这个最小值的,这样才有可能整体GCD等于它。因此,排序后从2开始遍历,如过能整除最小值,就GCD一下,默认放在了右边,其余不能整除最小值的不用管,默认放在了左边,没有任何影响。这样一来,最后再比较判断最终的GCD值是否等于a[1](即最小值)

AC代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=1e5+6;
int n,a[N];
void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	sort(a+1,a+1+n);
	int ans=0;
	for(int i=2;i<=n;i++)
	{
		if(a[i]%a[1]==0)
		ans=__gcd(ans,a[i]);
	}
	if(ans==a[1])cout<<"YES"<<endl;
	else cout<<"NO"<<endl;
}
signed main()
{
	IOS;
	int _=1;
	cin>>_;
	while(_--)
	solve();
	return 0;
}

C. Good Prefixes

题目来源
难度:1000

解题思路

什么是"好数组"?

  • 一个数组是"好数组",当且仅当里面存在一个元素,它等于数组中其他所有元素的总和。
    数组 [3, 1, 2] 是好数组,因为 3 = 1+2(第一个元素等于其他元素之和)
    数组 [2, 2, 3] 不是好数组,因为没有元素等于其他元素之和

需要计算这样的"好数组"前缀有多少个。

不难想到,要想是好数组,只能一个前缀中的最大值等于这个前缀中的其他值,那么我们可以用一个数组mx存储前i个数中的最大值,再用一个数组存前缀和,只要我们依次遍历,如果第i个位置的前缀和数组减去最大值还等于这个最大值的话,那他就是一个好数组。

AC代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=1e6+6;
int n,a[N],s[N],mx[N]; 
void solve()
{
	cin>>n;
	int ans=0;
	fill(s,s+1+n,0);
	fill(mx,mx+1+n,0);
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		mx[i]=max(mx[i-1],a[i]);//前i个元素中的最大值 
		s[i]=s[i-1]+a[i];//前缀和 
	}
	for(int i=1;i<=n;i++)
		if(s[i]-mx[i]==mx[i])ans++;
	cout<<ans<<endl;
}
signed main()
{
	IOS;
	int _=1;
	cin>>_;
	while(_--)
	solve();
	return 0;
}


B. Erase First or Second Letter

题目来源
难度:1100

解题思路

这道题很巧妙,操作一共就两种,删第一个和删第二个,如果删两次第一个和先删第一个再删第二个、先删第二个再删第一个都是完全相同的道理。这时候通过列举每种情况我们可以发现,只要判断第一个和第二个是否相同,然后利用动态规划的思想,其实就是前面已删除元素的去重之后的个数相加,就是最后能得出来的不同字符串个数。

AC代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=1e5+6;
int n;
char s[N];
void solve()
{
	cin>>n;
	int ans=0;
	for(int i=1;i<=n;i++)cin>>s[i];
	unordered_set<char>st;
	for(int i=1;i<=n;i++)
	{
		st.insert(s[i]);
		ans+=st.size(); 
	}
	cout<<ans<<endl;
	st.clear();
}
signed main()
{
	IOS;
	int _=1;
	cin>>_;
	while(_--)
	solve();
	return 0;
}


B. Digits

题目来源
难度:1100

解题思路

通过打表找规律即可,自己实践一下。

AC代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=1e6+6;
int n,d;
void solve()
{
	cin>>n>>d;
	cout<<1<<" ";
	if(n>=3||d%3==0)cout<<"3 ";
	if(d==5)cout<<"5 ";
	if(n>=3||d==7)cout<<"7 ";
	if(n>=6||d==9||(n>=3&&d%3==0))cout<<"9"; 
	cout<<endl;
}
signed main()
{
	IOS;
	int _=1;
	cin>>_;
	while(_--)
	solve();
	return 0;
}


C. Robin Hood in Town

题目来源
难度:1100

解题思路

哇塞终于做一道二分答案的题了。
二分答案不熟悉的小伙伴欢迎看我这篇博客:二分查找&二分答案【模板+例题】带你精通二分!
其实很简单,就是照着题意去模拟。首先让找最小值,用尽量向左找的模板,其次这里需要f标记一下,只要能找到就标记为1,后续输出时如果f值为0说明一个也找不到就输出-1.
主要就是check函数怎么去写了,这里我们可以将数组a复制给辅助数组b,防止这次模拟后的结果影响下一个结果,然后按题目要求进行操作,求出有多少人财富严格少于平均财富的一半,用ans记录。最后返回ans>n/2即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=1e6+6;
int n,a[N],b[N];
int check(int mid)
{
	double sum=0;
	for(int i=1;i<=n;i++)b[i]=a[i],sum+=b[i];
	sort(b+1,b+1+n);
	sum+=mid;
	b[n]+=mid;
	double x=1.0*sum/n/2;
	int ans=0;
	for(int i=1;i<=n;i++)
		if(b[i]<x)ans++; 
	return ans>1.0*n/2;
}
void solve()
{
	int f=0;
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	int l=0,r=1e18;
	while(l<r)
	{
		int mid=(l+r)/2;
		if(check(mid))r=mid,f=1;
		else l=mid+1; 
	}
	if(f)cout<<r<<endl;
	else cout<<"-1"<<endl;
	
}
signed main()
{
	IOS;
	int _=1;
	cin>>_;
	while(_--)
	solve();
	return 0;
}