算法继续刷起-2025年09月26日

  1. 现在需要在坐标平面上以某一点 C 为圆心画一个圆,且该圆心必须位于坐标轴上。

请你找到一个最小的半径r,使得这圆能够覆盖不少于[n/2]个给定点,并输出这个最小半径。

【名词解释】

坐标轴:包含x轴和y轴。x 轴表示形如(x,0)的所有点;y轴表示形如(0,y)的所有点。

覆盖:若点 P 到圆心 c 的欧氏距离不超过圆的半径,则称该圆覆盖点 P。

复制代码
#include<bits/stdc++.h>
using namespace std;
vector<pair<int,int>> points;
int n;
bool check(double mid){
	auto get = [&](int mode){
		vector<pair<double,int>> ans;
		for(auto p:points){
			if(mode == 0){
				if(fabs(p.second)>mid) continue;
				double d = sqrt(mid*mid - p.second*p.second);
				ans.emplace_back(p.first - d, 1);
				ans.emplace_back(p.first + d, -1);
			}else{
				if(fabs(p.first)>mid) continue;
				double d = sqrt(mid*mid - p.first*p.first);
				ans.emplace_back(p.second -d,1);
				ans.emplace_back(p.second + d,-1);
			}
		}
		sort(ans.begin(),ans.end(),[](const pair<double,int>& p1,const pair<double,int>& p2){
			if(p1.first == p2.first) return p1.second < p2.second;
			else return p1.first<p2.first;
		});
		int count =0;
		for(auto p:ans){
			count += p.second;
			if(count>=(n+1)/2) return true;
		}
		return false;
	};
	return get(0)||get(1);
}
int main(){
	cin>>n;
    points.resize(n);
	for(int i=0;i<n;i++){
		cin>>points[i].first>>points[i].second;
	}
	double lo = 0;double hi = 2e5;
	for(int i=0;i<50;i++){
		double mid = (lo + hi)/2;
		if(check(mid)) hi = mid;
		else lo = mid;
	}
	cout<<fixed<<setprecision(6)<<hi<<endl;
	return 0;
}
  1. 给出一个长度为 n 的序列 a1​,a2​,a3​...an​,按以下规则输出序列的中位数:

  2. 若序列长度为奇数,中位数是升序排序后中间的数字。

  3. 若序列长度为偶数:

    • 升序排序后,中间两数字 x=y 时,输出任意一个;
    • 升序排序后,中间两数字 x=y 时,输出 min(x,y)。
  • 输出中位数 midx 后,该数从序列消失,重复步骤直至序列元素全部输出。

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    int n;cin>>n;
    vector<int> nums(n);for(int i=0;i<n;i++)cin>>nums[i];
    sort(nums.begin(),nums.end());
    vector<int> ans;
    for(int i = (n-1)/2;i>=0;i--){
    ans.push_back(nums[i]);
    if(2*i == n-1) continue;
    ans.push_back(nums[n-1-i]);
    }
    for(int i=0;i<n;i++){
    if(i)cout<<" ";
    cout<<ans[i];
    }
    return 0;
    }

  1. 任何一个数 n 都可以拆成若干项不同的、由 2 的次幂和 3 的次幂相乘之和,即 n=2a1​×3b1​+2a2​×3b2​+⋯+2am​×3bm​ 且 2ai​3bi​=2aj​3bj​ (1≤i<j≤m) 。给定整数 n,找到长度为 m 的序列 a1​,a2​,⋯,am​ 和 b1​,b2​,⋯,bm​ 满足方程,并按由大到小顺序依次输出。

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    int t;cin>>t;
    while(t--){
    int n;cin>>n;
    vector<int> ans;
    while(n){
    int sum=0;
    int factor=1;
    while(factor2<=n){
    factor=factor
    2;
    }
    ans.push_back(factor);
    n -= factor;
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();i++){
    if(i)cout<<" ";
    cout<<ans[i];
    }
    cout<<endl;
    }
    return 0;
    }

  2. 小强最近在研究围棋,他希望有一个程序能告诉他一步之内,有哪些位置可以直接吃掉别人的棋子,吃几个。围棋可以在围住别人的情况下,吃掉别人的棋子。标准围棋的棋盘是19×19的,但小强只是想研究围棋的规则,故假定棋盘大小为n×n。

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    vector<vector<char>> mat;
    vector<vector<bool>> vit;
    int main(){
    cin>>n;
    mat.resize(n,vector<char>(n));
    vit.resize(n,vector<bool>(n));
    for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
    cin>>mat[i][j];
    }
    }
    int mx[4] = {0,0,1,-1};
    int my[4] = {1,-1,0,0};
    function<int(int,int)> f = [&](int x,int y){
    int ans=mat[x][y] == 'x';
    bool isall = true;
    bool iscan = false;
    for(int i=0;i<4;i++){
    int x_ = x + mx[i];
    int y_ = y + my[i];
    if(x_>=0 && y_>=0 && x_<n && y_<n && !vit[x_][y_]){
    if(mat[x_][y_] == '.') return -1;
    else if(mat[x_][y_] == 'o') continue;
    else{
    iscan = true;
    vit[x_][y_]=true;
    int res = f(x_,y_);
    if(res!=-1){
    ans += res;
    isall = false;
    }
    }
    }
    }
    if(isall && iscan){
    return -1;
    }
    else{
    return ans;
    }
    };
    vector<vector<int>> ans;
    for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
    if(mat[i][j] == '.'){
    vit[i][j]=true;
    int res = f(i,j);
    if(res>0)
    ans.push_back({i+1,j+1,res});
    }
    }
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();i++){
    cout<<ans[i][0]<<" "<<ans[i][1]<<" "<<ans[i][2]<<endl;
    }
    return 0;
    }

  3. 牛牛给出了一个关于未知量 x 的多项式。这个多项式以字符串的形式表示,它由若干个形如 (x−d)(x+d) 的括号表达式相乘构成,其中 d 是一个 1 到 9 之间的数字字符。牛牛想知道,当这个多项式完全展开后,x 的一次项(即 x^1 项)的系数是多少?请计算这个系数,由于答案可能很大,请将答案对 10007 取模后输出。

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    string s;cin>>s;
    vector<int> nums;
    auto split = &{
    int n = s.size();
    int factor = 1;
    int num=0;
    for(int i=0;i<n;i++){
    if(s[i] == 'x'||s[i] == '(') continue;
    else if(s[i] == '-'){
    factor = -1;
    }
    else if(s[i] == '+'){
    factor = 1;
    }
    else if(isdigit(s[i])){
    num = num * 10 + s[i] - '0';
    }
    else{
    nums.push_back(num*factor);
    num = 0;
    }
    }
    };
    int mod = 10007;
    auto quickmi = [&](int value,int m){
    int ans = 1;
    int factor = value;
    while(m){
    if(m&1)
    ans = (ans * factor)%mod;
    factor = (factor * factor)%mod;
    m>>=1;
    }
    return ans;
    };
    split();
    int res = 1;
    for(auto c:nums){
    res = (res * c)%mod;
    }
    int total = 0;
    for(auto c:nums){
    total = (total + (res * quickmi(c,mod-2))%mod)%mod;
    }
    cout<<total<<endl;
    return 0;
    }

  4. 给定一个整数,请你判断它是否可以写成4个质数之和。若可以,请输出任意一种方案;否则输出-1。

    #include <iostream>
    #include <cmath>
    using namespace std;

    bool is_prime(long long x) {
    if (x < 2) return false;
    if (x == 2) return true;
    if (x % 2 == 0) return false;
    for (long long i = 3; i * i <= x; i += 2) {
    if (x % i == 0) return false;
    }
    return true;
    }

    int main() {
    int t;
    cin >> t;
    while (t--) {
    long long n;
    cin >> n;
    if (n % 2 == 0) {
    long long m = n - 4;
    for (long long p = 2; ; p++) {
    if (is_prime(p) && is_prime(m - p)) {
    cout << "2 2 " << p << " " << m - p << endl;
    break;
    }
    }
    } else {
    long long m = n - 5;
    for (long long p = 2; ; p++) {
    if (is_prime(p) && is_prime(m - p)) {
    cout << "2 3 " << p << " " << m - p << endl;
    break;
    }
    }
    }
    }
    return 0;
    }

  5. 小红有一个数组,她每次可以让两个相邻的数字一起加一,她想知道把数组变成左右对称的最小操作次数。

左右对称的意思是将数组整体翻转后与原数组一致,例如:{1,2,3,3,2,1},{4,0,4}都是左右对称的,而{8,1,0,9,7,5},{9,2,2,7,6,8}都不是左右对称的。

复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;cin>>n;
	vector<int> nums(n);for(int i=0;i<n;i++) cin>>nums[i];
	int left = 0, right = n-1;
	int count = 0;
	while(left < right){
		if(nums[left]!=nums[right]){
			if(left == right - 1){
				cout<<-1<<endl;
				return 0;
			}
			else{
				if(nums[left] > nums[right]){
                    count += nums[left] - nums[right];
					nums[right-1] += nums[left] - nums[right];
					nums[right] = nums[left];
                    
				}
				else{
                    count += nums[right] - nums[left];
					nums[left+1] += nums[right] - nums[left];
					nums[left] = nums[right];
				}
			}
		}
		left++;
		right--;
	}
	cout<<count<<endl;
	return 0;
}
  1. 给出一个长度为n的序列a1,a2,...,n,求取出k个不同的区间,要求满足取出区间的区间和是t的倍数,求它们的区间和相加最大是多少?

一个区间的区间和即里面所有数相加,例如a=[4,3,5],区间[1,2]的和为7,区间{1,3]的和为12。

保证至少存在k个合法的区间。

复制代码
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int main(){
	int n,k,t;
	cin>>n>>k>>t;
	vector<int> nums(n);for(int i=0;i<n;i++) cin>>nums[i];
	vector<ll> pre(n+1);
	for(int i=1;i<=n;i++){
		pre[i] = pre[i-1] + nums[i-1];
	}
	priority_queue<ll, vector<ll>, greater<ll>> pq;
	vector<vector<int>> mem(t);
	mem[0].push_back(0);
	for(int i=1;i<=n;i++){
		int m = pre[i]%t;
		for(int j=0;j<mem[m].size();j++){
			if(pq.size()>=k && pre[i]-pre[mem[m][j]]>pq.top()){
				pq.pop();
			}
			pq.push(pre[i]-pre[mem[m][j]]);
		}
        mem[m].push_back(i);
	}
	ll ans = 0;
	while(!pq.empty()){
		ans += pq.top();
		pq.pop();
	}
	cout<<ans<<endl;
	return 0;
}
相关推荐
平平无奇。。。2 小时前
C++11之异常
开发语言·c++·visual studio
木头左2 小时前
跨周期共振效应在ETF网格参数适配中的应用技巧
开发语言·python·算法
almighty273 小时前
C# WPF实现ComboBox实时搜索与数据绑定
开发语言·c#·wpf·combobox
菜鸟小九3 小时前
SSM(MybatisPlus)
java·开发语言·spring boot·后端
数据知道3 小时前
Go基础:常用数学函数处理(主要是math包rand包的处理)
开发语言·后端·golang·go语言
学习同学3 小时前
从0到1制作一个go语言服务器 (一) 配置
服务器·开发语言·golang
大飞pkz3 小时前
【设计模式】桥接模式
开发语言·设计模式·c#·桥接模式
顾你&3 小时前
机器学习之无监督学习算法大总结
学习·算法·机器学习
数据知道3 小时前
Go基础:文件与文件夹操作详解
开发语言·后端·golang·go语言