Fox And Jumping CodeForces - 512B
原题链接
考察:数论+状压dp
思路:
很明显要选\(gcd(L_i) = 1\),且成本和最小的卡片.如果用背包dp会MLE.从单个考虑,枚举一个\(L_i\),它的质因数总数不超过9个.这里就可以用状压dp,枚举其他\(L_i\),如果不能整除质因子\(p\),就在那一位赋1,最后取最小值即可.
Code
#include <iostream>
#include <cstring>
using namespace std;
const int N = 310,M =10,INF = 0x3f3f3f3f;
int len[N],cost[N],n,f[1<<M],cnt,prime[M];
void GetDivide(int n)
{
cnt = 0;
for(int i=2;i<=n/i;i++)
{
if(n%i==0)
{
while(n%i==0) n/=i;
prime[cnt++] = i;
}
}
if(n>1) prime[cnt++] = n;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&len[i]);
for(int i=1;i<=n;i++) scanf("%d",&cost[i]);
int res = INF;
for(int i=1;i<=n;i++)
{//假定len[i]必选
GetDivide(len[i]);
memset(f,0x3f,sizeof f);
f[0] = cost[i];
for(int x=1;x<=n;x++)
{
int st = 0;
for(int j=0;j<cnt;j++)
if(len[x]%prime[j]!=0) st|=(1<<j);
for(int j=0;j<(1<<cnt);j++)
f[j|st] = min(f[j]+cost[x],f[j|st]);
}
res = min(res,f[(1<<cnt)-1]);
}
if(res!=INF) printf("%d\n",res);
else puts("-1");
return 0;
}