Vijos1921严厉的班长

传送门

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

第一眼看上去比较像搜索,其实是道状压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 }
时间: 2024-10-21 08:58:37

Vijos1921严厉的班长的相关文章

Vijos 1921 严厉的班长 【状态压缩动态规划】

严厉的班长 描述 木姑娘在班级里面是班长.虽然是副班长,却有着比正班长更高的威信,并深受小朋友们的爱戴. 每天眼保健操时间,木姑娘都要监督所有小朋友认真做眼保健操.整个过程被描述为n个时间段,第i个时间段内对于揉捏穴位的速度被要求为a[i]. 如果某一位小朋友在n个时间段内,速度分别为b[1],b[2],...,b[n],则他的最终得分为 score = |a[1]-b[1]| + |a[2]-b[2]| + ... + |a[n]-b[n]|. 分数越大,则说明表现越差,如果b[1]到b[n]

第11周项目2储存班长信息的学生类

/* *Copyright (c) 2016,烟台大学计算机学院 *All rights reserved. *文件名称 : *作 者 : 刘云 *完成日期 : 2016年5月8号 *版 本 号 : v6.0 * *问题描述 : 储存班长信息的学生类 *输入描述 : 无 *程序输出 : */ #include<iostream> using namespace std; class Stu //声明基类 { public: Stu(int n, string nam ); //基类构造函数 v

百度再次申明严厉打击垃圾外链 站长夹缝求生存

4.25日百度官方Lee再次发出外链申明,随着百度算法的更新,百度对外链的高质量要求越来越高,百度将严厉打击垃圾链接以及作弊链接.互联网的竞争压力越来越大,站长们做SEO优化难度越来越大,在百度的严厉打击下,站长们要怎样才能夹缝求生存?站长们还是跟着笔者一起来解读百度的算法,即使是夹缝也要生存下来. 新站切忌大量增加BBS签名外链 论坛签名外链是外链形式中最简单.操作最简单的外链方法,很多站长为了追求外链的数量,新站上线后并大量的投入力量做论坛签名外链,对于手工的签名外链质量还高点,很多站长为了

十一周 存储班长信息的学生类

#include <iostream> using namespace std; class Stu //声明基类 { public: Stu(int n, string nam ); //基类构造函数 void display( ); //成员函数,输出基类数据成员 protected: //(*)访问权限为保护型的数据成员 int num; //学生学号 string name; //学生姓名 }; class StuDetail: public Stu //声明派生类StuDetail

五个候选班长,20人投票。(输入1-5来表示支持哪个人)最后查看票数,看那个人胜出

for (; ; ) { Console.WriteLine("班长投票选举(1-5)"); Console.WriteLine("请选择你要投票的人:"); Console.WriteLine("1.张三"); Console.WriteLine("2.李四"); Console.WriteLine("3.王五"); Console.WriteLine("4.马六"); Console

淘宝严厉打击刷单,卖家应该如何进行突围?

今年电商普遍都很难做,因为阿里为了给美国的股民一个好看的报表,采取了严厉打击刷单的亮剑行动.卖家若再想通过刷单来带动销量,已经非常非常难了.阿里说的话,要想有饭吃,就给老子交保护费,要想吃到肉,就要交大把大把的保护费! 但是僧多粥少,即使真的给阿里交了保护费,很多时候,都只能喝到粥而已,甚至连粥都很难喝到.但是对于中小卖家来说,又有几个人能交的起保护费? 因此,广大卖家,不能坐以待毙,要通过各种方式来打破阿里的魔咒.这里小编给大家抛砖引玉,希望能给大家带来一些启发 米折.折800.卷皮.1折等网

15-07-08 数组-- 投票选班长

每班共有20个学生,投票选班长,总共有5个候选人,实现投票,并计算出得票最多的人以及他的票数 int [] tp = new int [20]; //每个人投的票 int [] ps = new int[5]; //每个人所得的票数 //投票 for (int i = 0; i < tp.Length; i++) { Console.WriteLine("支持一号请按1,支持二号请按2,支持三号请按3,支持四号请按4,支持五号请按5"); tp[i] = Convert.ToIn

投票选班长

static void Main46投票选班长(string[] args) { ////某班有20个学生,投票选班长,总共有5个候选人,实现投票,并且计算出得票最多的人以及他的票数. int[] tp = new int[20]; //每个人投的票 int[] ps = new int[5]; //每个候选人所得票数 for (int i = 0; i < tp.Length; i++) { Console.WriteLine("请投票,1代表第一个候选人,2代表第二个候选人--5带表第

C# 5 break continue 球员成绩 彩票 选班长

    二.新课: 1.break与continue. 这两个关键字一般放在循环的花括号里面使用. break--结束整个循环. continue--结束本次循环,进入下次循环. break的案例:     int i = 1;     for(;;)     {         if(i>100)         {             break;         }         Console.Write(i+"\t");         i++;     } co