Task
考虑正整数集合,现在有n组人依次来取数,假设第i组来了x人,他们每个取的数一定是x的倍数,并且是还剩下的最小的x个。
正整数中有m个数被标成了幸运数,问有哪些人取到了幸运数。
m<=1,000,000, n<=1,000,000, x<=1,000,000.
Solution
对于每个来的人数x(无论人数为x有几组),最多要计算 mxx 次, mx 为最大的幸运数,那么对于所有 x ,计算的总次数就是:
=mx(1+12+13+14+....+1maxx)
通过调和级数,可以确定暴力是足够的.因此直接记录每个x,当前的最小的倍数f[x]即可.再暴力更新,查找幸运数.
Code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#define ll long long
#include<queue>
using namespace std;
inline void rd(int &res){
res=0;char c;
while(c=getchar(),c<48);
do res=(res<<1)+(res<<3)+(c^48);
while(c=getchar(),c>=48);
}
inline void print(ll x){
if(!x)return ;
print(x/10);
putchar((x%10)^48);
}
inline void sc(ll x){
if(x<0){x=-x;putchar('-');}
print(x);
if(!x)putchar('0');
putchar('\n');
}
const int M=1000005;
int n,mark[M],rec[M];
ll A[M];
int main(){
int i,j,k,a,b,mx=0,m=0;
ll tot=0;
scanf("%d",&n);
for(i=1;i<=n;i++){
rd(a);
mark[a]=1;
mx=max(mx,a);
}
rd(n);
for(i=1;i<=n;i++){
rd(a);
int st=a,c=0;
if(rec[a]){
if(rec[a]<=mx)st=rec[a]+a;
else st=mx+1;
}
for(j=st;j<=mx;j+=a){
if(mark[j]==-1)continue;
else {
c++;
if(mark[j]==1)A[m++]=tot+c;
mark[j]=-1;
if(c==a)break;
}
}
rec[a]=j;
tot+=a;
}
printf("%d\n",m);
for(i=0;i<m;i++)sc(A[i]);
return 0;
}