1030 完美数列(25)(25 分)
给定一个正整数数列,和正整数p,设这个数列中的最大值是M,最小值是m,如果M <= m * p,则称这个数列是完美数列。
现在给定参数p和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数N和p,其中N(<= 10^5^)是输入的正整数的个数,p(<= 10^9^)是给定的参数。第二行给出N个正整数,每个数不超过10^9^。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:
8
完美数列 也就是 满足方程的最大覆盖数据中的数据个数。
思路 :
1. 先使得数据按照从小到大有序排序。
2.此时数据有序,这个时候遍历从 N-1号元素开始到 1 号元素结束,外部变量cnt记录覆盖的情况,如果此时的覆盖比上一次覆盖的个数要多就更新cnt否则就不更新。
3.传入 N-1号元素给子函数 计算最小满足方程的元素。子函数采用二分查找修改后的方法。定位最小范围 实现方法:
<< 找到范围中间的数判断是不是满足不等式,满足 移动 max的指针到这个元素,再动用二分修改查找,不满足,移动min指针到这个元素 再用二分修改查找 直到 二分值等于min所指元素的下标的时候 就break; 为什么?假设 min指针指向 1 号元素 max指针指向2号元素 (1+2)/2 是不是等于 1 如果这种情况不处理程序就会进入死循环。所以 一旦(类似) (1+2)/2 == min 那么就跳出。判断 min所指向元素是否满足方程 满足则返回 min元素的地址 否则由于前期的调整(红色处) 此时 max 所指向元素一定满足条件,返回max元素所指向元素的指针。>>(|||== 也就是说我尽量把 max指针指向可控范围,解答函数里做了一个判断 如果max都没有移动过 那么此次循环作废 一定不更新cnt)
好了 上代码吧 刚开始挺困扰我的 因为 一般思路是 排序 然后从这个元素 每一次都逐一往前遍历 找到范围,这样时间复杂度会比较高,此题还有部分不严谨的地方。在上完代码后会说一下:
#include <bits/stdc++.h>
using namespace std;
long long int a[100000 + 10];
int N, P;
long long int* efcz(int x) { // 位置
int minst = 0;
int maxst = x-1;
if (maxst < minst) // 1 可以删除 永远不会发生越界访问 我上了三个保险 这个是 保险2
return &a[minst];
while (maxst>minst) { // 2 这个判断条件是多余的 可以等价于 while(1) 何况我对一个元素还是上了保险 1 控制越界
int st = (maxst + minst) / 2;
if (minst == st) {
break;
}
else if (a[st] * P >= a[x]) {
maxst = st;
}
else {
minst = st;
}
}
if(a[minst]*P>=a[x]) // 保险 3
return &a[minst];
return &a[maxst];
}
void solve() {
scanf("%d%d", &N, &P);
for (int i = 0; i<N; i++)
scanf("%lld", &a[i]);
sort(a, a + N);
int cnt = 1;
for (int i = N - 1; i > 0; i--) { // i>0是保险 1
long long int* s = efcz(i);
if (s != &a[i - 1]) { // 3 测试系统忽略的错误
cnt = cnt<&a[i] - s + 1? &a[i] - s + 1 :cnt;
}
}
printf("%d\n", cnt);
}
int main() {
solve();
return 0;
}
我认为题目的样例没有考虑到的:
1.这个情况题目也没有处理。就是一串数字所组成的所有数列之中 全部都不满足条件的情况 这个时候 二分的指针将会指向 数列最大值的前一项 这个时候 假定这个数也不满足条件 那么 如果没有3 就会出现 cnt由1变成2的错误情况
题目没有考虑到的样例1 这个是显然的错误。虽然我学C 才不到三个月 ~ 这种问题应该是显而易见才对。
5 2
1 11 111 1111 11111
应该输出 1 去掉 if输出 2 但是去掉if 答案依然是正确的。所以我怀疑题目样例出的不全。但是网上的答案这个样例我试的均输出正确了(hahahaha~~~)。但是这个和样例问题没有半毛钱关系~
必须要艰苦奋斗,才能看见阳光。现在虽然辛苦,但是必须承认也在成长。起步晚怎么了?每次被嘲笑,我已经要受够了!!