洛谷七月月赛(未完)

题目描述

有一条宽度为 NN 的河上,小D位于坐标为 00 的河岸上,他想到达坐标为 NN 的河岸上后再回到坐标为 00 的位置。在到达坐标为 NN 的河岸之前小D只能向坐标更大的位置跳跃,在到达坐标为 NN 的河岸之后小D只能向坐标更小的位置跳跃。在河的中间有 MM 个岩石,小D希望能跳到每个岩石上恰好一次。由于小D的跳跃能力太强,小D的跳跃长度有个下限 SS ,但没有上限。现在请你判断他是否能够完成他的目标。

输入输出格式

输入格式:

第一行输入两个整数 N,M,SN,M,S ,分别表示河的宽度,岩石的数量和跳跃长度的下限。

第二行输入 MM 个整数,分别表示 MM 个岩石的坐标 w_1,w_2,\cdots,w_Nw1,w2,,wN 。保证 \{w_i\}{wi} 为递增序列。

输出格式:

如果小D可以完成他的目标,第一行输出YES,第二行输出 M+2M+2 个数,依次表示小D跳到的石头编号。特殊的,坐标为 00 的河岸编号为 00 ,坐标为 NN 的河岸标号为 M+1M+1 。如果有多种解法,允许输出任意一种。

如果小D不能完成他的目标,第一行输出NO

输入输出样例

输入样例#1:
6 1 3
3

输出样例#1:

YES
1 2 0

输入样例#2:

6 2 2
2 4

输出样例#2:

YES
2 3 1 0

输入样例#3:

5 2 3
2 3

输出样例#3:

NO

说明

1 \le N,S \le 1000001N,S100000

0 \le M < N0M<N

1 \le w_i < N1wi<N

题解:

首先我们考虑最靠近开头和最靠近结尾的两块岩石,如果他们离开头/结尾的距离小于 

SS ,那么这块岩石将不可能被跳到,从而导致无解。

对于三个连续的岩石 i,i+1,i+2i,i+1,i+2 ,如果 w_{i+2}-w_i<Swi+2wi<S ,由于我们只能来回一次,且每次跳到其中的一个石头上时必然不可能跳到另一个石头上,所以这种情况也会导致无解。

那么有解时我们只需要贪心地能跳就选择一个距离不小于 SS 的且最近的跳就可以了。

时间复杂度 O(N)O(N)

特别需要注意一个分类讨论的思想!!!

#include<iostream>
#include<cstdio>
using namespace std;

const int N = 1e5+10;
int n, m, s, w[N], ans[N];
bool vis[N];
int main() {
	scanf("%d%d%d", &n, &m, &s);
	int i;
	for (i = 1; i <= m; i++)
		scanf("%d", &w[i]);
	w[0] = 0, w[m+1] = n;
	int now = 0, cnt = 0;
	for (i = 1; i <= m+1; i++) {
		if (w[i]-now >= s) {
			ans[++cnt] = i;
			now = w[i];
			vis[i] = true;
		}
	}
	if (now != n) {
		printf("NO");
		return 0;
	}
	for (i = m; i >= 0; i--) {
		if (now-w[i]>=s && !vis[i]) {
			ans[++cnt] = i;
			now = w[i];
			vis[i] = true;
		}
	}
	if (cnt == m+2) {
		printf("YES\n");
		for (i = 1; i <= cnt; i++)
			printf("%d ", ans[i]);
	}
	else printf("NO");
	return 0;
}

题目描述

给定一个数字 AA ,这个 AA 由 a_1,a_2,\cdots,a_Na1,a2,,aN 相乘得到。

给定一个数字 BB ,这个 BB 由 b_1,b_2,\cdots,b_Mb1,b2,,bM 相乘得到。

如果 \frac{A}{B}BA 是一个质数,请输出YES,否则输出NO

输入输出格式

输入格式:

每个测试点包含多组数据,第一行读入一个整数 TT 表示数据组数,对于每组数据:

第一行输入两个整数 N,MN,M ,分别表示 AA 由 NN 个数字相乘得到, BB 由 MM 个数字相乘得到。

第二行输入 NN 个整数,分别表示组成 AA 的 NN 个数字。

第三行输入 MM 个整数,分别表示组成 BB 的 MM 个数字。

保证对于一个数字,其在 {b_i}bi 中出现的次数不多于在 {a_i}ai 中出现的次数。

输出格式:

对于每组数据:

如果 \frac{A}{B}BA 是一个质数,请输出YES,否则输出NO

在输出YESNO后输出一个换行符。

输入输出样例

输入样例#1:

2
3 2
5 7 7
5 7
4 2
5 7 7 7
5 7
输出样例#1:
YES
NO

说明

1 \le N \le 1000001N100000

0 \le M \le N0MN

1 \le a_i,b_i \le 10^{12}1ai,bi1012

1 \le T \le 101T10

\sum N \le 100000N100000

题解:

由于保证了任何一个数字在 bb 中的出现次数不大于在 aa 中的出现次数。

那么对于每个 bb 中的数字,我们只需要将其在 aa 中删去即可。

然后考虑如何判断 aa 剩下的数字是否为质数。

我们只需要检查每个数字由几个质数组成即可。

在判断质数时,发现当前已经有两个或以上的质数了需要马上退出,否则有可能会造成TLE。

值得一提的是,由 00 个质数组成的数字(即 11 )也不是质数。

复杂度 O(n\ log\ n + \sqrt a_i )O(n log n+ai)

其实要特别注意读题,即题面中加下划线的句子。

#include<iostream>
#include<cmath>
#include<map>
#include<cstdio>
using namespace std;

const int N = 1e5+10;
map<long long, int> mp;
int t, n, m;
long long a[N], b[N], c[N];
bool judge(long long  x) {
	if (x==0 || x==1) return false;
    int i;
    for (i = 2; i <= sqrt(x); i++) {
        if (!(x%i)) return false;
    }
    return true;
}
int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &m);
        int i, cnt = 0;
        long long x=-1;
    	for (i = 1; i <= n; i++)
            scanf("%lld", &a[i]);
        for (i = 1; i <= m; i++) {
        	scanf("%lld", &b[i]);
        	mp[b[i]]++;
        }
        for (i = 1; i <= n; i++)
			mp[a[i]]--;
		for (i = 1; i <= n; i++) {
			if (mp[a[i]]<0) {
				cnt++;
				x = a[i];
				mp[a[i]]++;
			}
			else continue;
		}
        if (cnt >= 2) {
        	printf("NO\n");
        	continue;
        }
        else {
        	if (cnt == 0) {
        		printf("NO\n");
        		continue;
        	}
			if(cnt == 1) {
				if (judge(x)) printf("YES\n");
				else printf("NO\n");
				continue;
			}
        }
    }
    return 0;
}

参考来源:

https://www.luogu.org/problemnew/show/P4753

https://www.luogu.org/problemnew/show/P4752

https://www.luogu.org/blog/FlierKing/luo-gu-7-yue-yue-sai-ti-xie

猜你喜欢

转载自blog.csdn.net/qq_38234381/article/details/81056605
今日推荐