码迷,mamicode.com
首页 > 其他好文 > 详细

Vijos1921严厉的班长

时间:2016-08-25 23:30:45      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:

传送门

在贴吧上看到了这道题,恰好最近在学相关的东西,觉得比较有意思就去做了。

第一眼看上去比较像搜索,其实是道状压DP。我简单讲一下思路:

首先明确,不管之前取了什么数,取1必定满足所有的数之间互质。而且如果出现最优的可以是1或者其他,那么1一定是更优的

再思考,对于每个读入的数,合适的范围必定是[1,2*a[i]-2]

而且a[i]<=30,这就很好搞了。

我们表出来所有小于58的素数,把每个数有哪几个素因子二进制表示出来。然后然后如果满足前一个状态&这个数,如果满足的话就更新条件。

 

 1 //Vijos 1921
 2 //by Cydiater
 3 //2016.8.25
 4 #include <iostream>
 5 #include <cstdio>
 6 #include <cstring>
 7 #include <ctime>
 8 #include <queue>
 9 #include <map>
10 #include <cmath>
11 #include <algorithm>
12 #include <iomanip>
13 #include <string>
14 #include <cstdlib>
15 using namespace std;
16 #define ll long long
17 #define up(i,j,n)       for(int i=j;i<=n;i++)
18 #define down(i,j,n)     for(int i=j;i>=n;i--)
19 const int MAXN=1<<16|1;
20 const int oo=0x3f3f3f3f;
21 inline int read(){
22       char ch=getchar();int x=0,f=1;
23       while(ch>9||ch<0){if(ch==-)f=-1;ch=getchar();}
24       while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
25       return x*f;
26 }
27 int prime[16]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
28 int a[MAXN],N,p[60],f[105][MAXN],ans=oo;
29 namespace solution{
30       inline int col(int num){
31             int tmp=0;
32             up(i,0,15)if(num%prime[i]==0)
33             tmp|=(1<<i);
34             return tmp;
35       }
36       void init(){
37             N=read();
38             up(i,1,N)a[i]=read();
39             up(i,1,58)p[i]=col(i);
40       }
41       void dp(){
42             up(i,0,N)up(S,0,(1<<16)-1)f[i][S]=oo;
43             f[0][0]=0;
44             up(i,1,N)up(S,0,(1<<16)-1)if(f[i-1][S]!=oo){
45                   f[i][S]=min(f[i][S],f[i-1][S]+abs(1-a[i]));
46                   if(a[i]==1)continue;
47                   up(j,2,2*a[i]-2)if(!(p[j]&S))f[i][S|p[j]]=min(f[i][S|p[j]],f[i-1][S]+abs(a[i]-j));
48             }
49       }
50       void output(){
51             up(S,0,(1<<16)-1)ans=min(ans,f[N][S]);
52             cout<<ans<<endl;
53       }
54 }
55 int main(){
56       //freopen("input.in","r",stdin);
57       using namespace solution;
58       init();
59       dp();
60       output();
61       return 0;
62 }

 

Vijos1921严厉的班长

标签:

原文地址:http://www.cnblogs.com/Cydiater/p/5808669.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!