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;
}

posted @ 2021-06-29 10:12  acmloser  阅读(47)  评论(0编辑  收藏  举报