先上题链接:click here
这题刚开始一看排序后无非就是对首部和尾部两种状态的操作,于是果断来一发dfs,然后就各种超时,即使是优化到以下代码这种优化到极致的代码,依然超时,卡在第四个测试点。
然后一看N最大为100000,那么用dfs时间复杂度为2^50000,不超时就有了鬼了。。。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <climits>
using namespace std;
const int MAXN = 100005;
const int INF = INT_MAX;
int p, ans;
int num[MAXN];
void dfs(int start, int end, int step){
if(step == ans) return;
if(start > ans) return;
if(num[start] >= (double)num[end]/p){
ans = step;
//printf("%d %d\n", start, end);
//printf("%d %d\n", num[start], num[end]);
return;
}
//printf("....\n");
step++;
dfs(start+1, end, step);
dfs(start, end-1, step);
}
int main(){
// freopen("in.txt", "r", stdin);
int N;
while(~scanf("%d %d", &N, &p)){
ans = INF;
for(int i = 0; i < N; i++){
scanf("%d", &num[i]);
}
sort(num, num+N);
dfs(0, N-1, 0);
printf("%d\n", N-ans);
}
return 0;
}
后来就想到了常规方法,两层for时间复杂度为n^2,找到最大完美数列长度时对小于这个长度的数列不予比较,结果依然各种超时,依旧卡在第四个测试点。
然后我就无奈了,看了题解,发现他们普遍都是在第二层for遍历时直接跳过了已知的最大完美数列长度,而不是我这种遍历了不符合才跳过。。。这种做法确实大大节省了时间。。可惜我没有想到。。能力不足吧。。
话说这题除了第四个测试点都弱爆了,pat的题不常做,可是这种题直接用第四个测试点就好了吧,干嘛要给人些安慰分呢,做不出来就是做不出来。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <climits>
using namespace std;
const int MAXN = 100005;
int main(){
// freopen("in.txt", "r", stdin);
int N, p, num[MAXN], ans;
while(~scanf("%d %d", &N, &p)){
ans = 0;
for(int i = 0; i < N; i++){
scanf("%d", &num[i]);
}
sort(num, num+N);
for(int i = 0; i < N; i++){
for(int j = i+ans; j < N; j++){
if(num[i] < (double)num[j]/p){//不是完美数列
ans = j-i;
break;
}
if(j == N-1) ans = N-i;//如果匹配到数列尾部还没有出现非完美数列元素,则完美数列元素为当前到尾部
}
}
printf("%d\n", ans);
}
return 0;
}