题目链接(牛客网复现赛)
**知识点:按底数分集合处理+二进制枚举
大佬的解析
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const int num=1e5+10;
LL a[num],b[num],c[num];
int db[num];
int n;
bool vis[num];
bool judge(int s,int t)
{
for(LL i=s*s;i<=t;i*=s)
{
if(i==t) return 1;
}
return 0;
}
LL solve(int cnt)
{
LL mx=0;
for(int i=0;i<(1<<cnt);i++)
{
int tot=0;LL temp=0;
for(int j=1;j<=cnt;j++)
{
if((i>>(j-1))&1){
c[++tot]=db[j];temp+=a[db[j]];
}
}
for(int s=1;s<=tot;s++)
{
for(int t=1;t<=tot;t++)
{
if(c[s]<c[t]&&judge(c[s],c[t]))
{
temp-=b[c[t]];
}
}
}
mx=max(temp,mx);
}
return mx;
}
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=n;i++) scanf("%lld",&b[i]);
LL ans=a[1];
for(LL i=2;i<=n;i++){
if(!vis[i]){
for(LL k=i*i;k<=n;k*=i){
vis[k]=1;
}
}
}
for(int i=2;i<=n;i++)
{
if(i*i<=n&&!vis[i]){
int cnt=0;
for(LL k=i;k<=n;k*=i) db[++cnt]=k;
ans+=solve(cnt);
}
else if(i*i>n&&!vis[i]){
ans+=a[i];
}
}
printf("%lld",ans);
return 0;
}