[BZOJ2793][Poi2012]Vouchers
2793: [Poi2012]Vouchers
Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 316 Solved: 148
[Submit][Status][Discuss]
Description
考虑正整数集合,现在有n组人依次来取数,假设第i组来了x人,他们每个取的数一定是x的倍数,并且是还剩下的最小的x个。
正整数中有m个数被标成了幸运数,问有哪些人取到了幸运数。
Input
第一行一个正整数m (m<=1,000,000),下面m行每行一个正整数x (x<=1,000,000),表示x是一个幸运数。
接下来一行一个正整数n (n<=1,000,000),下面n行每行一个正整数x (x<=1,000,000),表示这一组来了x个人。
Output
第一行输出一个非负整数k,表示k个人取到了幸运数,下面k行依次表示取到幸运数的人的编号,人按照来的顺序从1开始编号。
Sample Input
4
1
6
8
16
3
4
2
4
1
6
8
16
3
4
2
4
Sample Output
3
2
4
6
2
4
6
HINT
Hint
总共来了10个人,他们取走的数依次是4 8 12 16 2 6 20 24 28 32。
第2、4、6个人取到的是幸运数8、16、6。
(别把这题想太难,其实很水的)
Source
对于每一个x维护一个next数组,代表下一个x的位置,然后暴力处理即可。
简要估计一下上限复杂度$\sum\limits_{i=1}^n\frac mi=O(mlogn) 其中m=\max{a_i}$
不过肯定不会达到这个复杂度的
1 #include<cstdio> 2 #include<algorithm> 3 #define N 1000010 4 #define ll long long 5 using namespace std; 6 int n,next[N],maxn,tot,m,a[N]; 7 ll ans[N],sum,vis[N]; 8 int main() 9 { 10 scanf("%d",&n); 11 for(int i=1;i<=n;i++) 12 scanf("%d",&a[i]),maxn=max(a[i],maxn); 13 scanf("%d",&m); 14 while(m--) 15 { 16 int x; 17 scanf("%d",&x); 18 ll now=sum;sum+=x; 19 for(int i=x;i&&next[x]+x<=maxn;) 20 if(!vis[next[x]+=x]) 21 vis[next[x]]=++now,i--; 22 } 23 for(int i=1;i<=n;i++) 24 if(vis[a[i]]) 25 ans[++tot]=vis[a[i]]; 26 sort(ans+1,ans+tot+1); 27 printf("%d\n",tot); 28 for(int i=1;i<=tot;i++) 29 printf("%lld\n",ans[i]); 30 }
就让我永远不在这里写什么有意义的话--月下孤狼