test20181018 B君的第三题
Posted autoint
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了test20181018 B君的第三题相关的知识,希望对你有一定的参考价值。
题意
B 君的第三题(shenyang)
题目描述
客似云来,万里无云
B 君得到了一个数组({a_1,a_2,dots,a_n})。
B 君想通过修改让数组中个每对数都互质。
每次使一个数+1 或者-1 的代价是1。
不能将(a_i) 修改为0 或者负数。
问至少多少代价才可以让所有数两两互质。
输入格式
第一行一个整数n。
第二行n 个整数(a_i),表示数组初始值。
输出格式
一行一个数表示答案。
样例输入
5
2 4 6 8 10
样例输出
4
样例解释
修改为2, 3, 5, 7, 11。
数据规模与约定
对于100% 的数据,满足(1 leq n leq 100, 1 leq a_i leq 30)。
对于30% 的数据,满足(1 leq n leq 4)。
对于另30% 的数据,满足(1 leq a_i leq 10)。
分析
因为(a_i leq 30),1跟所有数互质,所以往下最多改到1,往上最多改到59,所以每个数所含质因数是固定的。
考虑dp,用(f(i,s))表示前i个数改动至只含s集合中的质因数且两两互质所需最小代价,转移方程为:
[
枚举i改成x,x所含质因数集合为s 枚举从原来的含k的集合转移过来,其中k与s没有交集 \
f(i,k∨s)=min_{x=1}^{59}f(i-1,k)+|a_i-x|
]
时间复杂度(O(n cdot 59 cdot 2^{17})),上界十分不紧。
代码
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#define rg register
#define il inline
#define co const
#pragma GCC optimize ("O0")
using namespace std;
template<class T> il T read()
{
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch==‘-‘)
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-‘0‘,ch=getchar();
return data*w;
}
template<class T> il T read(T&x)
{
return x=read<T>();
}
typedef long long ll;
const int INF=0x7fffffff;
int p[17]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59};
il int bit(rg int x)
{
rg int s=0;
for(rg int i=0;i<17;++i)
if(x%p[i]==0)
s|=(1<<i);
return s;
}
int b[60];
const int MAXN=107;
int f[MAXN][1<<17];
int main()
{
freopen("shenyang.in","r",stdin);
freopen("shenyang.out","w",stdout);
memset(f,0x3f,sizeof f);
f[0][0]=0;
rg int n=read<int>();
for(rg int i=1;i<=59;++i)
b[i]=bit(i);
for(rg int i=1;i<=n;++i)
{
rg int a=read<int>();
for(rg int j=1;j<=59;++j)
{
rg int ub=((1<<17)-1)^b[j];
for(rg int k=ub;;--k&=ub)
{
f[i][k|b[j]]=min(f[i][k|b[j]],f[i-1][k]+abs(a-j));
if(k==0)
break;
}
}
}
rg int ans=INF,up=(1<<17)-1;
for(rg int i=0;i<=up;++i)
ans=min(ans,f[n][i]);
printf("%d
",ans);
// fclose(stdin);
// fclose(stdout);
return 0;
}
以上是关于test20181018 B君的第三题的主要内容,如果未能解决你的问题,请参考以下文章