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; }
相关文章推荐
- 【BZOJ2793】【数学】[Poi2012]Vouchers
- 【BZOJ2793】[Poi2012]Vouchers 调和级数
- 【bzoj2793】[Poi2012]Vouchers 暴力
- BZOJ2793: [Poi2012]Vouchers
- bzoj 2793 [Poi2012]Vouchers 调和级数求和
- bzoj 2793 [Poi2012] Vouchers 调和级数
- BZOJ2793: [Poi2012]Vouchers
- BZOJ2793 [Poi2012]Vouchers 调和级数
- [BZOJ2793][Poi2012]Vouchers
- BZOJ 2793: [Poi2012]Vouchers(调和级数)
- BZOJ2793: [Poi2012]Vouchers
- bzoj2793: [Poi2012]Vouchers
- 2793: [Poi2012]Vouchers
- 2793 [Poi2012]Vouchers
- 【BZOJ】【P2793】【Poi2012】【Vouchers】【题解】【乱搞】
- bzoj 2802: [Poi2012]Warehouse Store
- BZOJ 2789 Poi 2012 Letters 树状数组 逆序对
- BZOJ2788: [Poi2012]Festival
- bzoj 2796: [Poi2012]Fibonacci Representation 记忆化搜索
- BZOJ 2802: [Poi2012]Warehouse Store