题目如下:
Given a sequence of positive integers and another positive integer p. The sequence is said to be a "perfect sequence" if M <= m * p where M and m are the maximum and minimum numbers in the sequence, respectively.
Now given a sequence and a parameter p, you are supposed to find from the sequence as many numbers as possible to form a perfect subsequence.
Input Specification:
Each input file contains one test case. For each case, the first line contains two positive integers N and p, where N (<= 10) is the number of integers in the sequence, and p (<= 10) is the
parameter. In the second line there are N positive integers, each is no greater than 10.
Output Specification:
For each test case, print in one line the maximum number of integers that can be chosen to form a perfect subsequence.
Sample Input:
10 8
2 3 20 4 5 1 6 7 8 9
Sample Output:
8
题目要求从给定序列中选取子序列,使得序列的最小值m、最大值M满足:M≤m*p,其中p为一个给定的正整数,输出能找到的最长子序列长度。
这道题一个很自然的思路就是设立一个头指针cur1,尾指针cur2,将序列按照升序排列,让cur2从最后一个元素向前指,cur1遍历从第一个元素到cur2的位置,找到合适的m时停下,记录长度,这样会有一个case超时,解决方法是让cur1从前到后遍历,cur2采用二分查找。
如果找到的位置使得M<m*p,说明M还可以更大,可以继续查找右半部分;如果M>m*p,说明M偏大,应该去左半部分找更小的;如果M=m*p,说明找到了合适的位置。在查找结束后,记录长度即可。
这段代码参考了Yangsongtao1991。
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
using namespace std; int main()
{
int n,p;
scanf("%d%d",&n,&p);
vector<long> seq(n);
for(int i = 0; i < n; i++)
scanf("%ld",&seq[i]);
sort(seq.begin(),seq.end());
int maxcount = 0, down = 1;
for(int i = 0; i < n; i++)
{
long mp = p * seq[i];
if(mp >= seq[n-1]) // 如果最大的元素都≤m*p,则从当前位置到最后全部计数。
{
if(maxcount < n - i){
maxcount = n - i;
}
break;
}
int up = n-1;
while(up > down)
{
// 二分查找,结束条件为上界≤下界,根据mid处的乘积判定。
// 现在是确定了m,要找M,如果找到的位置<mp,说明M可能可以更大,向右找;如果>mp,说明M偏大,向左找。
// 如果当前位置恰好满足,则说明已经找到了最长满足要求的位置。
int mid = (up + down)/2;
if(seq[mid] > mp)
up = mid;
else if(seq[mid] < mp)
down = mid + 1;
else
{
down = mid + 1;
break;
}
}
if(down - i > maxcount)
maxcount = down - i;
}
printf("%d\n",maxcount);
return 0;
}