BestCoder Round #85 前三题题解

1001

预处理前缀和,一旦有两个数模m的值相同,说明中间一部分连续子列可以组成m的倍数。 另外,利用抽屉原理,我

可以得到,一旦n大于等于m,答案一定是YES 复杂度 O(n)


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
int a[100010];
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,m;
		scanf("%d%d",&n,&m);
		bool s = false;
		for(int i=0;i<n;i++){
			scanf("%d",&a[i]);
			if(a[i]%m==0)	s = true;
		}
		if(n>m) s = true;
		if(!s){
			long long temp = 0;
			map<int ,int >mm;
			for(int i=0;i<n;i++){
				temp += a[i];
				mm[temp%m]++;
				if(temp%m==0||mm[temp%m]>=2){
					s = true;
					break;
				}
			}
		}
		printf("%s\n",s?"YES":"NO");
	}
return 0;
}


1002

首先骨牌只要考虑都往右推,其次能带倒骨牌的前提是高度大于等于距离+1。所以如果推一次,那么就是骨牌高度=

下一块骨牌距离+1. 把第一块左边距离设为无穷大,能推nk次,那么就是找nk块左边距离最大的向右推倒即可,所

需要排序找到前nk-1大的距离。 有个小trick,推的次数可能大于骨牌数量 复杂度 O(nlogn)


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,k;
		scanf("%d%d",&n,&k);
		priority_queue<int>q;
		long long r = n;
		for(int i=0;i<n-1;i++){
			int t;
			scanf("%d",&t);
			q.push(t);
		}
		if(k<n){
			for(int i=0;i<k-1;i++)	q.pop();
			while(!q.empty()){
				r += q.top();
				q.pop();
			}
		}
		printf("%I64d\n",r);
	}
return 0;
}


1003

由于y质因数分解式中每个质因数均出现2次,那么y是一个完全平方数,设y=z*z,题目可转换成求z,使得每个质因

出现1次. 我们可以暴力枚举z,检查z是否符合要求,显然当z是质数是符合要求,由素数定理可以得,z的枚举量在

logn级别 复杂度 O(\sqrt[4]{n}log\sqrt[2]{n}4nlog2n


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
#define N 50050
int n;
int prime[N];
void Get_prime(){
	bool t[N];
	memset(t,false,sizeof(t));
	n = 0;
	for(int i=2;i<N;i++){
		if(!t[i]){
			prime[n++] = i;
			for(int j=i+i;j<N;j+=i)	t[j] = true;
		}
	}
}
bool check(long long x){
	for(int i=0;i<n;i++){
		int count = 0;
		while(x%prime[i]==0){
			count++;
			x/=prime[i];
			if(count>=2)	return false;
		}
	}
	return true;
}
int main(){
	int T;
	scanf("%d",&T);
	Get_prime();
	while(T--){
		long long x;
		scanf("%I64d",&x);
		if(x<4){
			printf("%d\n",abs(x-4));
		}
		else{
			long long p,q;
			long long temp = sqrt(x);
			for(int i=0;;i--){
				if(check(i+temp)){
					p = i+temp;
					break;
				}
			}
			for(int i=1;;i++){
				if(check(i+temp)){
					q = i+temp;
					break;
				}
			}
			printf("%I64d\n",min(abs(p*p-x),abs(q*q-x)));
		}
	}
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值