CSP提高模拟赛(10.09)

反思:最小生成树没怎么见过题,单调题看得出来打不来。。。

T1 最大约数和

题面:给定一个正整数 S,现在要求你选出若干个互不相同的正整数,使得它们的和不大于 S,而且每个数的因数(不包括本身)之和最大。(S<=1000)
题解:O(n2)预处理约数和,然后01背包完事

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n,w[N];
int dp[N];
int main()
{
		for(int i=1;i<=1000;i++)
			for(int j=1;j<i;j++)
				if(i%j==0)w[i]+=j;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			for(int j=n-i;j>=0;j--)
			{
				dp[j+i]=max(dp[j+i],dp[j]+w[i]);
			}
		}
		printf("%d",dp[n]);

}

T2 最佳序列

题目:给一个长度为 n 的数组 A,给定 L, R,求所有满足长度大等于 L,小等于 R 的 A 数组的子区间的平均值的最大值。
题解:二分平均值,然后转成子问题,减去平均值后是否存在一段合法区间总值为正。这里我们可以用单调队列(区间滑动)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
int n,L,R;
int a[N];
double b[N],s[N];
int z[N],p1,p2;
bool check(double x)
{
	for(int i=1;i<=n;i++)b[i]=a[i]*1.0-x,s[i]=s[i-1]+b[i];
	double ans=0;p1=1;p2=0;
	for(int i=L;i<=n;i++)
	{
		while(p1<=p2&&i-z[p1]>R)p1++;
		while(p1<=p2&&s[z[p2]]>s[i-L])p2--;
		z[++p2]=i-L;
		ans=max(ans,s[i]-s[z[p1]]);
	}return ans>0;
}
int main()
{
	double maxx=0;
	scanf("%d%d%d",&n,&L,&R);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]),maxx=max(maxx,(double)a[i]);
	double l=0,r=maxx,mid;
	while(r-l>1e-10)
	{
		mid=(l+r)/2;
		if(check(mid))l=mid;
		else 		  r=mid;
	}
	printf("%.4lf",l);
}

T3 贸易

题目:选择若干条边,使每个点的入度为1,问最小总边权
题解:很容易想到最小生成树+生成树外最短边(基环树)。但考虑联通块可以拆开建最小生成树。于是我就不会了。。。
//-------------------------------------------------
考虑最小生成树的加边法(忘名了),用并查集维护是否在树内,另开数组维护每个并查集是否成环;
按边权排序后:1,两点在同一树中,无环就加边变有环。2,两点都在有环树中(异树),就不连边;3,两点异树(可能某个在有环树中)或未分配,连边。
最后统计是否每个点都连过了,不然输出No。
//---------听说费用流可以骗60分-----------

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int ans=0;bool f=1;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=1;s=getchar();}
	while(s>='0'&&s<='9')
	{
		ans=(ans<<1)+(ans<<3)+(s&15);
		s=getchar();
	}return f?ans:-ans;
}
const int N=5e5+10;
int n,m;
struct qu{int u,v,w;bool operator < (const qu x)const{return w<x.w;}}e[N];
int f[N];
int fa(int x){return (x==f[x])?x:f[x]=fa(f[x]);}
bool h[N];
int main()
{
	n=read();m=read();
	for(int i=1;i<=m;i++)
	{
		e[i].u=read();e[i].v=read();e[i].w=read();
	}sort(e+1,e+m+1);
	for(int i=1;i<=n;i++)f[i]=i;
	int cnt=0;long long ans=0;
	for(int i=1;i<=m;i++)
	{
		int u=fa(e[i].u),v=fa(e[i].v);
		if(u==v)
		{
			if(!h[u])//情况1
			{
				ans+=e[i].w;
				cnt++;h[u]=1;
			}
		}
		else
		{
			if(h[u]&&h[v])continue;//情况2
			h[u]=h[u]|h[v];
			f[v]=u;cnt++;
			ans+=e[i].w;//情况3
		}
	}
	if(cnt==n)printf("%lld",ans);
	else	  printf("No");
}
资源来源于网络,如有侵权,私信立删。 CSP-J/S第一轮时间 CSP-J/S第一轮分为:CSP-J1和CSP-S1。和NOIP第一轮时间一样,CSP-J/S第一轮认证在10月份第三个星期六进行。 CSP-J/S第一轮考察重点 第一轮认证为笔试或机试,主要测试选手有关计算机方面的基本知识,第一轮为资格测试。从2020年开始,全部为机试。 CSP-J/S第一轮报名方式 参加CSP-S/J两组两轮认证均须在网上注册报名,注册网站为http://rg.noi.cn。参加认证者必须如实填写个人信息报名,包括但不限于姓名、身份证号、出生日期、性别、就学(学籍学校)/就职单位等,信息一旦注册,不得修改,如有错误,责任自负。 CSP-J/S第一轮认证考点 省认证点由CCF授权的CSP非专业级别省认证组织单位设置。 1、第一轮认证点:由省认证组织单位总负责人设置,每个认证点人数不应少于20人。 2、未经批准的认证点,其认证成绩不予承认。 认证费用 第一轮CSP-S/J组:50元/人(该费用不包括食宿及交通费)。 CSP-J/S第一轮认证试题组成 CSP-J/S第一轮在10月份第三个星期六进行,其中CSP-J1认证时间为周六9:30-11:30,CSP-S1认证时间为周六14:30-16:30。考试时长为2小时,内容为笔试或机试(从2020年开始全部为机试),满分100分。 试题由三部分组成: ① 选择题(共15题,每题2分,共计30分) CSP-S1的前10道题为单选题,后10道题为不定项选择题(只有全部选对才得分,否则不得分);CSP-J1的前15道题都是单选题。 ② 程序阅读理解题(共3题,共计40分) 题目给出一段程序(不一定有关于程序功能的说明),考生通过阅读理解该段程序进行答题,分为选择题和判断题。 ③ 程序完善题(共3题,共计30分) 题目给出一段关于程序功能的文字说明,然后给出一段程序代码,在代码中略去了若干个语句或语句的一部分并在这些位置给出空格,要求考生根据程序的功能说明和代码的上下文,选择对应答案 。三题皆为选择题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值