思路:考虑得出,最终的集合一定是gcd=1的集合,那么我们枚举n个数中哪个数必须选,然后把它质因数分解,由于质数不会超过9个,可以状态压缩,去得出状态为0的dp值就是答案。
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 #include<iostream> 6 int n,l[305],c[305],p[3005],val[30005],f[305][1025]; 7 int read(){ 8 int t=0,f=1;char ch=getchar(); 9 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 10 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 11 return t*f; 12 } 13 int main(){ 14 n=read(); 15 int ans=1<<30; 16 for (int i=1;i<=n;i++) 17 l[i]=read(); 18 for (int i=1;i<=n;i++) 19 c[i]=read(); 20 for (int i=1;i<=n;i++){ 21 int tot=0,t=l[i]; 22 for (int j=2;j*j<=t;j++){ 23 if (t%j==0){ 24 tot++;p[tot]=j; 25 while (t%j==0) t/=j; 26 } 27 } 28 if (t!=1) p[++tot]=t; 29 for (int j=1;j<=n;j++) 30 if (j!=i){ 31 val[j]=0; 32 for (int k=1;k<=tot;k++) 33 if (l[j]%p[k]==0) 34 val[j]|=1<<(k-1); 35 } 36 int sum; 37 val[i]=sum=(1<<tot)-1; 38 for (int j=1;j<=n;j++) 39 for (int k=0;k<=sum;k++) 40 f[j][k]=1<<30; 41 f[i][sum]=c[i]; 42 for (int j=i;j<=n-1;j++) 43 for (int k=0;k<=sum;k++) 44 if (f[j][k]!=1<<30){ 45 f[j+1][k]=std::min(f[j+1][k],f[j][k]); 46 f[j+1][k&val[j+1]]=std::min(f[j+1][k&val[j+1]],f[j][k]+c[j+1]); 47 } 48 if (f[n][0]!=1<<30){ 49 ans=std::min(ans,f[n][0]); 50 } 51 } 52 if (ans!=1<<30) printf("%d ",ans); 53 else 54 printf("-1 "); 55 return 0; 56 }