PAT-B1030 完美数列 (25 分)(思路)
- 题意:给出n个数,在这n个数中找出一个长度最长的序列,要求在这个序列中,最大数字小于等于最小数字*参数P。求序列最长长度
- 思路:刚明白题意的时候感觉题目好复杂,不知道用什么算法去写,直接参考csdn上的的博客,明白了需要用到双重循环,同时复杂的问题一下子清晰明了了。
- step1:对读入数据,并从小到大排序。
- step2:首先设置最终得到的序列长度为mmax=0(由此记录循环过程中得到的最大的序列长度);接下去用两个循环来求解。
- step3:第一层(for i=0;i<n;i++)这里的i为最小数的下标的索引。第二层for(j=i+mmax;j<n;j++)这里的j为此时遍历到的最大的数的下标索引,当满足a[i]*p>=a[j]时,就可以让mmax=j-i+1;不满足时,跳出j循环。就这样,一直遍历下去,因为mmax一直保存的是已经求出的最大的长度,因此循环过程中的逻辑一直是正确的,一般循环到j<n之后就可以得出结果了。
- step4:给一组数据可以模拟一下:2 3 20 4 5 1 6 7 8 9 20 50 80 100 300 500
OK!思路写完了,去写代码~
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll n,p;//注意要用long long类型,因为p*a[i]运算过程中可能会超10^9;
cin>>n>>p;
ll a[100010];
for(int i=0;i<n;i++)
scanf("%lld",&a[i]);
sort(a,a+n);
ll mmax=0;//首先设置求得的最长序列长度为0;
for(int i=0;i<n;i++)//最小数下标
{
for(int j=mmax+i;j<n;j++)//j=mmax+1我觉得是整个算法的核心,就是如果遇到不满足a[i]*p>=a[j]时,break后进入i+1之后的循环
{
//进入i+1之后的循环后j同样随着mmax+1也加了1,最大元素指向了刚刚不满足条件的下一个,好经典
if(a[j]<=a[i]*p)
mmax=j-i+1;
else
break;//a[j]不满足,那其之后的数都不满足,直接break。
}
}
printf("%lld",mmax);
}
思路参考第二个