【无标题】


C. Removing Smallest Multiples

题目直达

筛倍数
题意:给定n,集合S里有从1到n总共n个数,给定一个长度为n的字符串表示集合T,s[i]=1则i在T中存在,s[i]=0则不存在, 把S改成T,每次可以选S中存在的数k,然后删除k的最小倍数,这样操作花费为k,求S变成T的最小花费
题解:两层循环,外层从1枚举到n,每次 枚举i的倍数,如果这个数在T中不存在并且之前没有删掉过这个数(s[j]!=2), 就以i为花费删掉这个数,并把s[j]标记为2,如果存在就停止。

#include<iostream>
#include<cstring>
#include<algorithm>
#include <queue>
#include <map>
#include <cmath>
#include <set>
#include <vector> 
#define x first
#define y second
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N=1e6+10;
char s[N];

/*
     题意:给定n,集合S里有从1到n总共n个数,给定一个长度为n的字符串表示集合T,s[i]=1则i在T中存在,s[i]=0则不存在,
	       把S改成T,每次可以选S中存在的数k,然后删除k的最小倍数,这样操作花费为k,求S变成T的最小花费
     题解:两层循环,外层从1枚举到n,每次 枚举i的倍数,如果这个数在T中不存在并且之前没有删掉过这个数(s[j]!=2),
	       就以i为花费删掉这个数,并把s[j]标记为2,如果存在就停止。 
*/

void solve()
{
	int n; cin>>n;
	scanf("%s",s+1);
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=i;j<=n&&s[j]!='1';j+=i)
		{
			ans+=i*(s[j]!='2');
			s[j]='2';
		}
	}
	printf("%lld\n",ans);
}

signed main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);cout.tie(0);
	int t=1; cin>>t;
	while(t--)
	{
		solve();
	}
	
	return 0;
}

B. Meeting on the Line

题目直达

浮点二分
题意:有n个人要到一个地方集合,每人要从a[i]出发,出发前要打扮t[i]分钟,走一单位的距离要花费1时间,求最合适的集合的位置,使得集合时间最短

题解:二分位置肯定是不可以的,因为它两边的性质一样,但是可以二分时间,这样每个点都会有一个在这个时间内能够到达的区间范围,求出所有点的区间范围的交集,没有交集就需要一个更大的时间让他们有交集,否则就找有没有更小的时间,最终的交集会趋近于一个点,这个点就是最终答案

#include<iostream>
#include<cstring>
#include<algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector> 
#include <cmath>
#define x first
#define y second
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N=1e5+10;
double ans;
double a[N],t[N];
int n;
/*
    浮点二分
	题意:有n个人要到一个地方集合,每人要从a[i]出发,出发前要打扮t[i]分钟,走一单位的距离要花费1时间,求
	      最合适的集合的位置,使得集合时间最短
	题解:二分位置肯定是不可以的,因为它两边的性质一样,但是可以二分时间,这样每个点都会有一个在这个时间内能够到达的区间范围,
	      求出所有点的区间范围的交集,没有交集就需要一个更大的时间让他们有交集,否则就找有没有更小的时间,
		  最终的交集会趋近于一个点,这个点就是最终答案 
*/
bool check(double mid)
{
	double l=-2e18,r=2e18;
	for(int i=1;i<=n;i++)
	{
		if(t[i]>mid) return false;
		l=max(l,a[i]-(mid-t[i]));
		r=min(r,a[i]+mid-t[i]);
	}
	if(r-l>=1e-8) ans=l;
	return r-l>=1e-8;
}

void solve()
{
	ans=0;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>t[i];
	
	double l=0,r=2e18;
	for(int i=0;i<100;i++)
	{
		double mid= (l+r)/2.0; 
		if(check(mid)) r=mid;
		else l=mid;
	}
	
	printf("%.8lf\n",fabs(ans));
	
}

signed main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);cout.tie(0);
	int t=1; cin>>t;
	while(t--)
	{
		solve();
	}
	
	return 0;
}

C. Game Master

题目直达

贪心
题意: n个人对战n-1局,每个人有两个数ai,bi,每个回合任意挑选两个人的任意值,数字大的人获胜,最终留下一个人胜利,问每个人是否有能赢的可能,有输出1没有0
题解:先对每个人的第一个数从大到小排序,第一个位置必定能赢,然后比较b, 先记录第一个数的b,now=b,再往后寻找,如果有一个位置的b大于now,那么从now那个位置到此处的位置都可以赢,将now重新为从起始位置到此位置的最小值, 继续寻找,直至没有位置的b比now更大

#include<iostream>
#include<cstring>
#include<algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector> 
#define x first
#define y second
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N=1e5+10;
typedef struct node
{
	int a,b,id;
}DATE;
DATE stu[N];
int ans[N];

bool cmp(DATE l,DATE r)
{
	return l.a >r.a ;
}

void solve()
{
	/*
	贪心 
	题意: n个人对战n-1局,每个人有两个数ai,bi,每个回合任意挑选两个人的任意值,数字大的人获胜,最终留下一个人胜利,
	      问每个人是否有能赢的可能,有输出1没有0
	题解:先对每个人的第一个数从大到小排序,第一个位置必定能赢,然后比较b, 先记录第一个数的b,now=b,再往后寻找,
	      如果有一个位置的b大于now,那么从now那个位置到此处的位置都可以赢,将now重新为从起始位置到此位置的最小值,
		  继续寻找,直至没有位置的b比now更大 
	*/ 
	int n; cin>>n;
	for(int i=1;i<=n;i++)
	{
		stu[i].id=i; ans[i]=0; cin>>stu[i].a;
	}
	for(int i=1;i<=n;i++) cin>>stu[i].b;
	
	sort(stu+1,stu+1+n,cmp);
	
	int now=stu[1].b,t=stu[1].b;
	int id=1;
	for(int i=2;i<=n;i++)
	{
		if(stu[i].b >now)
		{
			id=i;
			now=min(now,t);
		}
		else t=min(t,stu[i].b);
	}
	for(int i=1;i<=id;i++) ans[stu[i].id]=1;
	
	for(int i=1;i<=n;i++)
	{
		cout<<ans[i]; 
	}
	cout<<"\n";
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int t=1; cin>>t;
	while(t--)
	{
		solve();
	}
	
	return 0;
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值