SMU Summer 2024 Contest Round 1(7.8)zhaosang

A-A
http://162.14.124.219/contest/1005/problem/A
一道数学问题,求概率。
要求成功的概率,有两个色子, 一个用来抛正反面,一个用来控制得分大小,当超过某个得分值,答案正确。
模拟一下,如果考虑失败的情况太多,我们只需要考虑正确的情况,贪心就是每次都是正面,得分翻倍,直到大于等于k值

#include<bits/stdc++.h>
using namespace std;

using ll =long long;
set<ll>st;
ll ma[100001];
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll n,k;
	double ans=0.0;
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		ll res=i;
		double cnt=1.000000000000/n;
		while(res<k){
			cnt*=0.5000000;
			res*=2;
		}
		ans+=cnt;
	}
	cout<<setprecision(12)<<ans;
}
C-C

http://162.14.124.219/contest/1005/problem/C
这道题就是让你从上往下涂颜色,要求颜色数量尽可能小,如果出现相同颜色要求后面的值大于前面。
思考一下,颜色数量少,那我们尽可能只用几种颜色,如果后面的值大于前面的,那么后面可以覆盖前面的颜色,
然后把颜色的最小值更新,如果后面的值大于等于已经使用的颜色的最大值,这个时候创建一个新的颜色,以此类推。

代码如下:

#include<bits/stdc++.h>
using namespace std;

using ll =long long;
set<ll>st;
ll ma[100001];
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll n,ans=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		ll a;
		int pd=0;
		cin>>a;
		if(i==1){
			ans++;
			ma[1]=a;
		}else{
			
		for(int j=1;j<=ans;j++){
			if(a>ma[j]){
				ma[j]=a;
				pd=1;
				break;
			}
		}
		if(pd==0){
			ans++;
			ma[ans]=a;
		}
		}
	}
	cout<<ans;
}

F-F
http://162.14.124.219/contest/1005/problem/F
这道题做了挺久,一开始没想明白,只能两个循环然后剪枝,后面想法出来后是贪心。

答案最大,那么让尽可能大的数加到原数组,使用我们只需要从大到小把数加到原数组从小到大排序
,这样最大的值依次替换成最小的值,如果没有替换的数没有比原数组大,说明此时已经是最大值

#include <bits/stdc++.h>
using namespace std;

using ll =long long;

struct Node{
	ll x,y;
}q[1000010];
ll v[1000010];
ll n,m;
bool cmp(Node a,Node b){
	return a.y>b.y;
}
int main(){
	
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>v[i];
	sort(v+1,v+n+1);
	for(int i=1;i<=m;i++)cin>>q[i].x>>q[i].y;
	sort(q+1,q+1+m,cmp);
	int j=1;
	for(int i=1;i<=n;i++){
		if(q[j].x==0)j++;
		if(v[i]<q[j].y&&q[j].x>0)v[i]=q[j].y,q[j].x--;
		else if(v[i]>q[j].y)break;
		
	}
	ll sum=0;
	for(int i=1;i<=n;i++)sum+=v[i];
	cout<<sum;
	
	
}
B-B(——补题)

https://atcoder.jp/contests/abc128/tasks/abc128_d
后面我补题的时候也没有思路,看学长的代码可能是我比较笨,不知道为什么这样可以取到最大。
我去看了很多题解发现也看不懂,我就知道太弱了,后面找了一篇很若只的教学看懂了,分享一下。
就是枚举然后每次都停下来检查自己,每左边加一个或者右边加一个就停下来,如果加有负数就记录一下,
然后检查自己,如果还有操作次数,那么可以减掉有的负数,然后继续左边右边加。取答案最大值即可

代码如下:

/*////////ACACACACACACAC///////////
  . Code by Ntsc .
  . WHY NOT????? .
  /*////////ACACACACACACAC///////////

#include<bits/stdc++.h>
#define ll long long
#define db double
#define rtn return
using namespace std;

const int N=1e5;
const int M=1e5;
const int Mod=1e5;
const int INF=1e5;

ll n,m,ans,sum,k;
ll t[N],v[N];


signed main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>v[i];
	}
	for(int ia=0;ia<=n&&ia<=k;ia++){//枚举A
		for(int ib=0;ib+ia<=n&&ib+ia<=k;ib++){//枚举B
			int cnt=0;sum=0;
			for(int i=1;i<=ia;i++)t[++cnt]=v[i],sum+=v[i];
			for(int i=1;i<=ib;i++)t[++cnt]=v[n-i+1],sum+=v[n-i+1];
			sort(t+1,t+cnt+1);
			int c=k-ia-ib;//计算C
			for(int i=1;i<=c&&i<=cnt;i++){
				if(t[i]>0)break;//一直丢到没有负数或者操作数达到k或者t中没有剩余元素
				sum-=t[i];//从t中挑选出负数,丢掉
			}
			ans=max(ans,sum);
		}
	}
	cout<<ans<<endl;
	return 0;
}
posted @ 2024-07-14 17:06  冬天的睡袋  阅读(45)  评论(0编辑  收藏  举报