【jzoj5280】【NOIP提高组模拟A组8.15】【膜法师】

题目大意

【jzoj5280】【NOIP提高组模拟A组8.15】【膜法师】_第1张图片

解题思路

可以发现g小于等于k+1时,只要小于g的数的个数不超过f就是合法的。对于g大于k+1时,统计a在取值范围内有多少个a是g的倍数,可以发现每个a只会贡献一次,开一个桶记录即可,时间复杂度是调和级数nlogn。

code

#pragma GCC optimize(2)
#include
#include
#include
#include
#define LL long long
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define fr(i,j) for(int i=begin[j];i;i=next[i])
#define f2(i,j) for(int i=begi2[j];i;i=nex2[i])
using namespace std;
int const mn=2*1e6+9,inf=1e9+7;
int t,n,k,f,a[mn],b[mn];
int max(int x,int y){
    return (x>y)?x:y;
}
int read(){
    char ch=getchar();
    while((ch<'0')||(ch>'9'))ch=getchar();
    int v=0;
    while((ch>='0')&&(ch<='9'))v=v*10+ch-'0',ch=getchar();
    return v;
}
int c[20];
void write(int v){
    c[0]=0;
    while(v){
        c[++c[0]]=v%10;
        v/=10;
    }
    fd(i,c[0],1)putchar(c[i]+'0');
    putchar(' ');
}
int main(){
    scanf("%d",&t);
    fo(cas,1,t){
        scanf("%d%d%d",&n,&k,&f);
        int mx=0,mi=inf;
        fo(i,1,n){
            a[i]=read();
            b[max(a[i]-k,1)]++,b[a[i]+1]--;
            mx=max(mx,a[i]);
        }
        sort(a+1,a+n+1);
        fo(i,1,mx)b[i]+=b[i-1];
        int lim=k+1,tmp;
        if(f+1<=n)lim=min(lim,a[f+1]);
        fo(i,1,lim)write(i);
        int j;
        fo(i,k+2,mx){
            tmp=0;
            for(j=i;j<=mx;j+=i)tmp+=b[j];
            if(tmp>=n-f)write(i);
        }
        fo(i,1,mx)b[i]=0;
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(jzoj,数论)