第一场cf

5 篇文章 0 订阅
5 篇文章 0 订阅

我的第一场,虽然是教育厂,但还是留下做个纪念把


第二题,给出n个数,求两数之和是2的幂次方的数对个数

:这题最后想出了map,但是感觉自己弱到爆了,map用的方法不对,wa。。。。

(这题我本来想卡时卡过去,可十万的数据范围直接不可能,一万都不好卡,100000根本不行,毕竟两层循环在那里了)


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
int n,a[100005],b[100005],num[100005];
map<int,int> mp;
int main()
{
	scanf("%d",&n);
	int x;
	long long ans=0;
	for (int i=1;i<=n;i++) 
	{
		scanf("%d",&x);
		for (int j=1;j<=30;j++) ans+=mp[(1ll<<j)-x];//因为2的次幂就那么多,枚举次幂,判断是否出现过,和出现了几次,这用map就很好办
		mp[x]++;//把现在这个数加入到map中,供以后计算对数
	}
	printf("%I64d",ans);	
	return 0;
}

刚刚突然发现,原先的代码只要爆mp【x】--;提到上面来就能过。。。

因为一个数不能和自己组合,而前面的数已经和他配对过,所以到它时只需用在意他后面的数,他自己也不能算

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
int n,a[100005],b[100005],num[100005];
map<int,int> mp;
int main()
{
	scanf("%d",&n);
	int x;
	for (int i=1;i<=n;i++) scanf("%d",&b[i]),mp[b[i]]++;
 	long long ans=0;
	for (int i=1;i<=n;i++)
	{
		mp[b[i]]--;
		for (int j=1;j<=30;j++) 
			ans+=mp[(1<<j)-b[i]];
	}
	printf("%I64d",ans);	
	return 0;
}

第三题:

给定数轴上n个city(点),和m个cellular network tower的点

求最小的半径,使得tower的信号可以覆盖所有city

n<=1e5;

显然二分。。。同时,只要数据范围差不多到int的极限了(1e9) 那么就要开 long long!!,反正多耗不了多少内存

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
int n,m;
ll a[100005],b[100005];
bool ok(ll mid)
{
	int j=1;
	for (int i=1;i<=n;)
	{
		if (abs(b[j]-a[i])<=mid) {i++;continue;}
		if (a[i]<b[j]) 
			return false;
		else 
		{
			j++;
			if (j>m) return false;
		}
	}
	return true;
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) scanf("%I64d",&a[i]);
	for (int i=1;i<=m;i++) scanf("%I64d",&b[i]);
	ll l=0,r=2*1e9,mid,ans=0;
	while (l<=r)
	{
		mid=(l+r)>>1;
		if (ok(mid)) {ans=mid;r=mid-1;}
		else l=mid+1;	
	}
	printf("%I64d",ans);
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值