您的位置:首页 > 其它

JZOJ 5280 膜法师

2017-08-28 20:33 148 查看


好啰嗦......还好作者给了一句话题意,不然光看题就很耗费时间。

样例输入:

1
6 3 1
78 69 55 102 233 666

样例输出:

1 2 3 4 5 6 11

数据范围:



思路:

首先思路肯定就是暴力,因为原题暴力能拿60分 o( ̄3 ̄)o

然后发现数据保证ai不大于2000000

诶......那就是说可以开个桶的水平?

好\(^o^)/~

开一个数组统计每个数出现了多少次,维护一个前缀和

因为对于每一个满足条件的g,必有一个区间和的值在n-f以上,且这个区间属于集合 {h*g~h*g+k | h=1,2,3,4.....}

所以只要枚举全部可能的g,对于每一个g枚举h=1~floor(A/g),其中A是ai的最大值

代码:

然而蒟蒻的我因为被卡常数加了输入输出优化和特判(所有小于k的g),还是跑的没有一众dalao快 -_-||

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define ll long long
using namespace std;
ll n,k,f,a[3001000],x[3001000],maxn,sum[5001000];
inline ll read()
{
ll data=0,w=1; char ch=0;
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
return data*w;
}
inline void write(ll x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int main(){
//    freopen("mogician19.in","r",stdin);
//    freopen("000000000001.out","w",stdout);
ll t,i,g,tmp;t=read();ll tttt=t;
while(t--){
memset(a,0,sizeof(a));memset(x,0,sizeof(x));memset(sum,0,sizeof(sum));
maxn=0;
//        scanf("%d%d%d",&n,&k,&f);
n=read();k=read();f=read();
for(i=1;i<=n;i++){
//            scanf("%d",&a[i]);
a[i]=read();
x[a[i]]++;maxn=max(maxn,a[i]);
}
for(i=1;i<=maxn+k;i++) sum[i]=sum[i-1]+x[i];
printf("1 ");
for(g=2;g<=min(maxn/2+10,maxn);g++){
tmp=0;
if(g<=k+1){
if(sum[g-1]<=f){
write(g);putchar(' ');
}
continue;
}
for(i=1;i<=maxn/g;i++){
tmp+=sum[g*i+k]-sum[g*i-1];
}
if(n-f<=tmp){
write(g);putchar(' ');
}
}
putchar('\n');
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: