• 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;
    }
    
    静渊以有谋,疏通而知事。
  • 相关阅读:
    *****Exercise 4.1 Generate a multiplication table
    Exercise 3.4 A calculator that allows multiple calculations
    Exercise 3.3 Calculate a discounted price
    Exercise 3.2 Display a date
    理解Java异常处理机制
    eclipse远程Debug配置
    [转]java代码性能优化总结
    [转]A星寻路算法
    JVM参数配置
    Gradle笔记(1) 安装
  • 原文地址:https://www.cnblogs.com/autoint/p/9825412.html
Copyright © 2020-2023  润新知