题目大意
有数列ai,共有n个数。你要给
又有
每个位置i能获得收益
1≤n≤2×105,ri∈[0,263),bi,vi∈(0,104)
题目分析
不要被题意弄蒙蔽了,令d(i)表示i约数个数,那么
d数组可以使用类
显然前面的数只会对后面的数做贡献。因此我们从小到大填数,如果当前该位的fi等于ri,那我们就让这位填bi就可以满足条件了,否则不填即可。还是使用类Eratosthene筛法更新后面的位置的fi。
由于bi∈N+,因此答案一定能将贡献拿满。
时间复杂度O(nln n)。
是不是被秀了一脸。
代码实现
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
int read()
{
int x=0,f=1;
char ch=getchar();
while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=200500;
int b[N],d[N];
LL r[N],now[N];
bool s[N];
LL ans;
int n;
void pre()
{
for (int i=1;i<=n;i++)
for (int j=i;j<=n;j+=i)
d[j]++;
}
void solve()
{
for (int i=1;i<=n;i++)
if (r[i]==now[i])
{
now[i]+=b[i],s[i]=true;
for (int j=i;j<=n;j+=i)
now[j]+=1ll*b[i]*d[j/i];
}
}
int main()
{
freopen("reimu.in","r",stdin),freopen("reimu.out","w",stdout);
n=read();
for (int i=1;i<=n;i++) b[i]=read();
for (int i=1;i<=n;i++) r[i]=read();
for (int i=1;i<=n;i++) ans+=read();
pre(),solve();
printf("%d\n",ans);
for (int i=1;i<n;i++) putchar('0'+s[i]),putchar(' ');
printf("%d\n",s[n]);
fclose(stdin),fclose(stdout);
return 0;
}