1030. 完美数列

给定一个正整数数列,和正整数p,设这个数列中的最大值是M,最小值是m,如果M <= m * p,则称这个数列是完美数列。

现在给定参数p和一些正整数,请你从中选择尽可能多的数构成一个完美数列。

输入格式:

输入第一行给出两个正整数N和p,其中N(<= 105)是输入的正整数的个数,p(<= 109)是给定的参数。第二行给出N个正整数,每个数不超过109

输出格式:

在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。

输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:

8


算法:

  1. 算法开始。
  2. 读入N和p。
  3. 读入所有数字,存于a[N],排序。
  4. i=0,max=0。
  5. 如果a[i]*p>a[N-1],则跳到
  6. 用二分法找出大于a[i]*p的最小数字的下表j。
  7. 如果j-i小于max而且如果p等于1或者j-i不等于1,max等于j-i。
  8. 回到第五步。
  9. 如果n-i小于max而且如果p等于1或者n-i不等于1,max等于n-i。
  10. 输出max。
  11. 算法结束。

#include<stdio.h>
#include<stdlib.h>
int cmp(const void* v1, const void* v2);
int find_min_larger(int* array, int i, int p, int n);
int main(void) {
	int n, p;
	int i, j;
	int* array;
	int max = 0;
	double num;
	scanf_s("%d %d", &n, &p);
	array = (int*)calloc(n, sizeof(int));
	for (i = 0; i < n; i++) {
		scanf_s("%d", array + i);
	}
	qsort(array, n, sizeof(int), cmp);
	num = (double)(array[0]) * (double)p;	
	for (i = 0; (num = (double)(array[i]) * (double)p) < array[n - 1]; i++) {
		j = find_min_larger(array, i, p, n);
		if ((j - i > max)&&(j - i != 1 || p == 1)) {
			max = j - i;
		}
	}
	if ((n - i > max) && ((n - i != 1)||p==1)) {
		max = n - i;
	}
	printf("%d", max);
	return 0;
}

int cmp(const void* v1, const void* v2) {
	if (*((int*)v1) > *((int*)v2)) {
		return 1;
	}
	else if(*((int*)v1)==*((int*)v2)){
		return 0;
	}
	else {
		return -1;
	}
}

int find_min_larger(int* array, int i, int p, int n) {
	int start = i + 1, end = n - 1, middle;
	double num = p*array[i];
	while (start < end) {
		if (num < array[start]) {
			return start;
		}
		else if (num >= array[end]) {
			return end + 1;
		}
		else{
			middle = (start + end) / 2;
			if (array[middle] > num) {
				end = middle - 1;
			}
			else {
				start = middle + 1;
			}
		}
	}
	if (num < array[start]) {
		return start;
	}
	else {
		return start + 1;
	}
}

上段代码对二分查找法的使用不是特别漂亮,现在修改如下。
#include<stdio.h>
#include<stdlib.h>
int cmp(const void* v1, const void* v2);
int find_min_larger(int* array, int i, int p, int n);
int main(void) {
    int n, p;
    int i, j;
    int* array;
    int max = 0;
    double num;
    scanf("%d %d", &n, &p);
    array = (int*)calloc(n, sizeof(int));
    for (i = 0; i < n; i++) {
        scanf("%d", array + i);
    }
    qsort(array, n, sizeof(int), cmp);
    num = (double)(array[0]) * (double)p;
    for (i = 0; (num = (double)(array[i]) * (double)p) < array[n - 1]; i++) {
        j = find_min_larger(array, i, p, n);
        if ((j - i > max)&&(j - i != 1 || p == 1)) {
            max = j - i;
        }
    }
    if ((n - i > max) && ((n - i != 1) || p == 1)) {
        max = n - i;
    }
    printf("%d", max);
    return 0;
}

int cmp(const void* v1, const void* v2) {
    return *((int*)v1) - *((int*)v2);
  }

int find_min_larger(int* array, int i, int p, int n) {
    int start = i + 1, end = n - 1, middle;
    double num = p * array[i];
    while (start < end) {
        middle = (start + end) / 2;
        if (num < array[middle]) {
            end = middle;
        }
        else{
            start = middle + 1;
        }
    }
    return start;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值