题目:
Pang believes that one cannot make an omelet without breaking eggs.
For a subset A of {1,2,…,n}, we calculate the score of A as follows:
- Initialize the score as 0.
- For any i∈A, add ai to the score.
- For any pair of integers (i, j) satisfying i≥2, j≥2, i∈A and j∈A, if there exists positive integer k > 1 such that i^k=j, subtract bj from the score.
Find the maximum possible score over the choice of A.输入描述:
The first line contains a single integer n(1≤n≤100000).
The second line contains n integers a1,a2,…,an(1≤ai≤1000000000)
The third line contains n integers b1,b2,…,bn(1≤bi≤1000000000).输出描述:
Print a single integer x --- the maximum possible score.输入1:
4 1 1 1 2 1 1 1 1
输出1:
4
输入2:
4 1 1 1 1 1 1 1 2
输出2:
3
题意:从集合{1,2,,,n}中选出一个子集A。对于任意i>=2,j>=2,如果满足i^k=j,则减掉b[j]。求这个子集的最大值。
思路:先把{ 2,3,,n}按底数分组,2的幂次数为一组,3的幂次数为一组,以此类推,因为只有在同一组中才可能出现i^k=j的情况。然后分组来处理,具体做法是对每一组用二进制枚举所有可以产生的组合,题目要求的是如果满足i^k=j,则减掉b[j],可以先把枚举出来的a[i]全部加起来,把对应的下标记录下来,然后遍历找有没有i^k=j的情况,如果有就减掉b[j]。枚举该组的所有组合能产生的值,再取一个最大值,即为该分组的最大值。求出每一组的最大值最后加起来即为答案。
#include <iostream>
using namespace std;
typedef long long ll;
ll a[100005],b[100005],m[100005],vis[100005]= {0},c[100005],ans1;
int is_mi(ll a,ll b)
{
for(ll i=a;i<=b;i*=a)
if(i==b)return 1;
return 0;
}
int main()
{
ios::sync_with_stdio(false);
int n,k=0;
cin>>n;
for(int i=1; i<=n; i++)
cin>>a[i];
for(int i=1; i<=n; i++)
cin>>b[i];
ans1=a[1];
for(int i=2; i<=n; i++)
{
ll max1=0,ans=0;
if(!vis[i])
{
k=0;
for(ll j=i; j<=n; j*=i)//按底数分组
{
m[k++]=j;
vis[j]=1;
}
for(int h=0; h<(1<<k); h++)//二进制枚举
{
ans=0;
int t=0;
for(int l=0; l<k; l++)
{
if(h&(1<<l))
{
ans+=a[m[l]];
c[t++]=m[l];
}
}
for(int x=0; x<t; x++)//减去其中i^k=j的情况
for(int y=0; y<t; y++)
{
if(c[x]>c[y]&&is_mi(c[y],c[x]))
ans-=b[c[x]];
}
max1=max(max1,ans);//枚举该组的所有组合后取一个最大值
}
}
ans1+=max1;//所有分组的最大值相加
}
cout<<ans1;
return 0;
}