您的位置:首页 > 其它

bzoj 2793: [Poi2012]Vouchers 乱搞

2017-10-09 20:30 274 查看

题意

考虑正整数集合,现在有n组人依次来取数,假设第i组来了x人,他们每个取的数一定是x的倍数,并且是还剩下的最小的x个。

正整数中有m个数被标成了幸运数,问有哪些人取到了幸运数。

第一行一个正整数m (m<=1,000,000),下面m行每行一个正整数x (x<=1,000,000),表示x是一个幸运数。

接下来一行一个正整数n (n<=1,000,000),下面n行每行一个正整数x (x<=1,000,000),表示这一组来了x个人。

第一行输出一个非负整数k,表示k个人取到了幸运数,下面k行依次表示取到幸运数的人的编号,人按照来的顺序从1开始编号。

分析

因为取到大于最大的幸运数的数是对答案没有影响的,所以实际能取的数不超过1e6。那么我们可以开一个桶a[x]表示取x的倍数的人从头开始取取到了哪个数,然后每次一直往后跳即可。

复杂度O(nlogn)

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long LL;

const int N=1000005;

int a
,tot;
LL ans
;
bool vis
,tag
;

int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}

int main()
{
int m=read(),mx=0;
for (int i=1;i<=m;i++)
{
int x=read();
tag[x]=1;mx=max(mx,x);
}
int n=read();LL now=0;vis[0]=1;
while (n--)
{
int x=read();
for (int i=1;i<=x;i++)
{
while (vis[a[x]]&&a[x]+x<=mx) a[x]+=x;
if (!vis[a[x]])
{
vis[a[x]]=1;
if (tag[a[x]]) ans[++tot]=now+i;
}
else break;
}
now+=x;
}
printf("%d\n",tot);
for (int i=1;i<=tot;i++) printf("%lld\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: