Codeforeces Round #585 (Div.2)

本文深入解析算法竞赛中的关键策略,包括最大最小化问题、产品数量计算、字母交换、游戏策略、强连通分量分析及2-SAT问题的扩展。通过具体题目示例,展示如何运用编程技巧解决复杂算法挑战。

正题

      Portal

A. Yellow Cards

      最大的肯定就是每一个球员依次黄牌。

      最小的就是将每个球员都恰好先罚剩一张,再一直罚。

#include<bits/stdc++.h>
using namespace std;
 
int n,a1,a2,k1,k2;
 
int main(){
	scanf("%d %d %d %d %d",&a1,&a2,&k1,&k2,&n);
	int temp=max(n-a1*(k1-1)-a2*(k2-1),0);
	printf("%d ",temp);
	if(k1>k2) swap(k1,k2),swap(a1,a2);
	if(n>a1*k1) printf("%d",a1+(n-a1*k1)/k2);
	else printf("%d",n/k1);
}

B. The Number of Products

       跟ai的值无关,我们把-1的点标出来,然后枚举-1的位置算答案就可以了。

#include<vector>
#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
 
const int N=200010;
int n;
int a[N];
vector<int> f;
int g[2]; 
 
int main(){
	scanf("%d",&n);
	f.push_back(0);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]<0?f.push_back(i),1:0;
	f.push_back(n+1);
	int now=0;
	long long ans1=0,ans2=0;
	for(int i=1;i<f.size();i++){
		long long temp=f[i]-f[i-1]-1;
		ans2+=(1+temp)*temp/2;
	}
	for(int i=f.size()-2;i>0;i--){
		g[now]+=f[i+1]-f[i];
		ans1+=1ll*(f[i]-f[i-1])*g[now];
		ans2+=1ll*(f[i]-f[i-1])*g[now^1];
		now^=1;
	}
	printf("%I64d %I64d",ans1,ans2);
}

C. Swap Letters

      只有两种对(a,b),(b,a)

      两个相同的对交换一次就可以。不同两个对最多一对。

      记得判断-1即可。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
 
const int N=200010;
int n;
char a[N],b[N];
int f[N],g[N];
int t1,t2;
 
int main(){
	scanf("%d",&n);
	scanf("%s",a+1);
	scanf("%s",b+1);
	for(int i=1;i<=n;i++) if(a[i]!=b[i]){
		if(a[i]=='a') f[++t1]=i;
		else g[++t2]=i;
	}
	if((t1+t2)&1) printf("-1");
	else{
		if(t1&1) printf("%d\n",t1/2+t2/2+2);
		else printf("%d\n",t1/2+t2/2);
		for(int i=2;i<=t1;i+=2) printf("%d %d\n",f[i],f[i-1]);
		for(int i=2;i<=t2;i+=2) printf("%d %d\n",g[i],g[i-1]);
		if(t1&1){
			printf("%d %d\n",f[t1],f[t1]);
			printf("%d %d\n",f[t1],g[t2]);
		}
	}
}

D. Ticket Game

      有用的只有四个东西,左边的和,右边的和,左边的问号个数,右边的问号个数

      如果一边的值和问号比另一边都严格小,那么先手必胜。

      否则就在值小的那边填问号,若差为9的倍数,而且问号个数为偶数,那么后手必胜,否则还是先手必胜。

#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
 
const int N=200010;
int n;
char s[N];
 
int main(){
	scanf("%d",&n);
	scanf("%s",s+1);
	int l=0,r=0,le=0,ri=0;
	for(int i=1;i<=n/2;i++) s[i]=='?'?le++:l+=s[i]-'0';
	for(int i=n/2+1;i<=n;i++) s[i]=='?'?ri++:r+=s[i]-'0';
	if(le>ri) swap(le,ri),swap(l,r);
	ri-=le;l-=r;
	if(l<0 || ri%2==1 || l%9 || l/9!=ri/2) printf("Monocarp");
	else printf("Bicarp");
}

E. Marbles

      处理出来两两交换的次数。

      然后直接暴力Dp转移就可以了。

#include <ctime>
#include <cstdio>
#include <random>
#include <algorithm>
#include <ctime>
#include <iostream>
#include <queue>
#include <bitset>
#include <string>
#include <cstring>
#include <cmath>
#define log lg
#include <unordered_map>
using namespace std;
const int N = 1e6;
int n;
vector<int>g[21];
int log[1<<20];
long long f[1<<20], a[20][20];
int main() {
    scanf("%d", &n);
    for (int i = 0; i < 20; i ++)
        log[1<<i] = i;
    for (int i = 1; i <= n ; i ++){
        int x;
        scanf("%d", &x);
        g[x - 1].push_back(i);
    }
    for (int i = 0; i < 20; i ++)
        for (int j = 0; j < 20; j ++)
            if (i != j && g[i].size() && g[j].size()) {
                int pos2 = 0;
                for (int pos1 = 0; pos1 < g[i].size(); pos1 ++){
                    while (pos2 < g[j].size() - 1 && g[j][pos2 + 1] < g[i][pos1]) pos2 ++;
                    if (g[i][pos1] > g[j][pos2])
                        a[i][j] += pos2 + 1;
                }
            }
    for (int i = 1; i < (1 << 20); i ++)
        if ((i&-i) != i)
            f[i] = 1e18;
    for (int i = 1;i < (1 << 20); i ++){
        int x = i ^ ((1 << 20) - 1);
        while (x) {
            int xx = x & -x;
            int y = i;
            long long v = f[i];
            while (y) {
                v += a[log[y & -y]][log[xx]];
                y -= y & -y;
            }
            f[xx + i] = min(f[xx + i], v);
            x -= xx;
        }
    }
    cout<<f[(1<<20) - 1];
    return 0;
}

F. Radio Stations

      最后一题题面太长了。

      这道题如果没有功率的限制,显然就是一个裸的2-sat

      考虑将功率的限制也放在图上:如果选择了功率i,那么功率区间不包含它的点只能不选,连边即可

      但是这样建图的边数是o(n^2),需要优化

      将功率区间分为两种,一种在这个点前面,另一种在这个点的后面

      同样将功率也裂成两个点,分别连向这两种区间,因为功率i的第1种点一定是功率i+1的第一种点的子集,因此(i+1)1->i1和功率右区间恰好在i+1的点,同理(i-1)2->i2和功率左区间恰好为i-1的点

      对图求强连通,如果裂成的两个点中在同一个强连通就不行,否则所有选1的区间都要选,功率是最大的i2

#include<bits/stdc++.h>
using namespace std;
#define N 1600005
struct ji{
    int nex,to;
}edge[N<<2];
int E,n,m,m1,m2,x,y,ans,head[N],vis[N],dfn[N],low[N],s[N];
void add(int x,int y){
    edge[E].nex=head[x];
    edge[E].to=y;
    head[x]=E++;
}
void dfs(int k){
    dfn[k]=low[k]=++x;
    s[++s[0]]=k;
    for(int i=head[k];i!=-1;i=edge[i].nex){
        int v=edge[i].to;
        if (!dfn[v]){
            dfs(v);
            low[k]=min(low[k],low[v]);
        }
        else
            if (!vis[v])low[k]=min(low[k],dfn[v]);
    }
    if (dfn[k]==low[k]){
        vis[k]=++vis[0];
        while (s[s[0]]!=k)vis[s[s[0]--]]=vis[0];
        s[0]--;
    }
}
int main(){
    scanf("%d%d%d%d",&m1,&n,&m,&m2);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=m1;i++){
        scanf("%d%d",&x,&y);
        add(2*x-1,2*y);
        add(2*y-1,2*x);
    }
    for(int i=1;i<=n;i++){
        scanf("%d%d",&x,&y);
        add(2*i,2*n+2*x);
        add(2*n+2*x-1,2*i-1);
        if (y<m){
            add(2*i,2*n+2*y+1);
            add(2*n+2*y+2,2*i-1);
        }
    }
    for(int i=1;i<=m2;i++){
        scanf("%d%d",&x,&y);
        add(2*x,2*y-1);
        add(2*y,2*x-1);
    }
    for(int i=1;i<m;i++){
        add(2*n+2*i+2,2*n+2*i);
        add(2*n+2*i-1,2*n+2*i+1);
    }
    x=0;
    for(int i=2;i<=2*(n+m);i+=2)
        if (!dfn[i])dfs(i);
    for(int i=1;i<=2*(n+m);i+=2)
        if (!dfn[i])dfs(i);
    for(int i=1;i<=n+m;i++)
        if (vis[2*i-1]==vis[2*i]){
            printf("-1");
            return 0;
        }
    for(int i=1;i<=n;i++)ans+=(vis[2*i]<vis[2*i-1]);
    for(int i=m;i;i--)
        if (vis[2*n+2*i]<vis[2*n+2*i-1]){
            printf("%d %d\n",ans,i);
            for(int j=1;j<=n;j++)
                if (vis[2*j]<vis[2*j-1])printf("%d ",j);
            return 0;
        }
}

 

【电力系统】单机无穷大电力系统短路故障暂态稳定Simulink仿真(带说明文档)内容概要:本文档围绕“单机无穷大电力系统短路故障暂态稳定Simulink仿真”展开,提供了完整的仿真模型与说明文档,重点研究电力系统在发生短路故障后的暂态稳定性问题。通过Simulink搭建单机无穷大系统模型,模拟不同类型的短路故障(如三相短路),分析系统在故障期间及切除后的动态响应,包括发电机转子角度、转速、电压和功率等关键参数的变化,进而评估系统的暂态稳定能力。该仿真有助于理解电力系统稳定性机理,掌握暂态过程分析方法。; 适合人群:电气工程及相关专业的本科生、研究生,以及从事电力系统分析、运行与控制工作的科研人员和工程师。; 使用场景及目标:①学习电力系统暂态稳定的基本概念与分析方法;②掌握利用Simulink进行电力系统建模与仿真的技能;③研究短路故障对系统稳定性的影响及提高稳定性的措施(如故障清除时间优化);④辅助课程设计、毕业设计或科研项目中的系统仿真验证。; 阅读建议:建议结合电力系统稳定性理论知识进行学习,先理解仿真模型各模块的功能与参数设置,再运行仿真并仔细分析输出结果,尝试改变故障类型或系统参数以观察其对稳定性的影响,从而深化对暂态稳定问题的理解。
本研究聚焦于运用MATLAB平台,将支持向量机(SVM)应用于数据预测任务,并引入粒子群优化(PSO)算法对模型的关键参数进行自动调优。该研究属于机器学习领域的典型实践,其核心在于利用SVM构建分类模型,同时借助PSO的全局搜索能力,高效确定SVM的最优超参数配置,从而显著增强模型的整体预测效能。 支持向量机作为一种经典的监督学习方法,其基本原理是通过在高维特征空间中构造一个具有最大间隔的决策边界,以实现对样本数据的分类或回归分析。该算法擅长处理小规模样本集、非线性关系以及高维度特征识别问题,其有效性源于通过核函数将原始数据映射至更高维的空间,使得原本复杂的分类问题变得线性可分。 粒子群优化算法是一种模拟鸟群社会行为的群体智能优化技术。在该算法框架下,每个潜在解被视作一个“粒子”,粒子群在解空间中协同搜索,通过不断迭代更新自身速度与位置,并参考个体历史最优解和群体全局最优解的信息,逐步逼近问题的最优解。在本应用中,PSO被专门用于搜寻SVM中影响模型性能的两个关键参数——正则化参数C与核函数参数γ的最优组合。 项目所提供的实现代码涵盖了从数据加载、预处理(如标准化处理)、基础SVM模型构建到PSO优化流程的完整步骤。优化过程会针对不同的核函数(例如线性核、多项式核及径向基函数核等)进行参数寻优,并系统评估优化前后模型性能的差异。性能对比通常基于准确率、精确率、召回率及F1分数等多项分类指标展开,从而定量验证PSO算法在提升SVM模型分类能力方面的实际效果。 本研究通过一个具体的MATLAB实现案例,旨在演示如何将全局优化算法与机器学习模型相结合,以解决模型参数选择这一关键问题。通过此实践,研究者不仅能够深入理解SVM的工作原理,还能掌握利用智能优化技术提升模型泛化性能的有效方法,这对于机器学习在实际问题中的应用具有重要的参考价值。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值