http://codeforces.com/contest/703/problem/E

题意:

给出n个数和一个k,计算出至少要多少个数相乘才是k的倍数。

思路:
这道题目参考了杭电大神的代码http://blog.csdn.net/snowy_smile/article/details/52134304

对于每个数字,我们要么选,要么不选,这就很像01背包。但是肯定是需要预处理的。

对于每个数字,它所贡献的数就是它和k的最大公因数,这个不难理解吧。

所以我们可以把k的所有因子计算出来,因为有些因子很大,所以这里离散化一下,用map映射,这样后面才开得了数组。

我们用f[i][j]表示前i个数字,它们的gcd乘=映射j状态时的最佳方案。

当我们分析到第i个数字时,它所能贡献的数就是gcd(a[i],v[j]),那么它的前缀就是v[j]/gcd(a[i],v[j]),具体参见代码。

 #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
using namespace std;
typedef long long LL;
const int maxn=+; int n;
LL k;
LL s;
LL a[maxn];
LL b[maxn];
pair<int,LL> f[maxn][maxn*];
vector<LL> v;
map<LL,LL> key; LL gcd(LL a,LL b)
{
if(a<b) swap(a,b);
while(b!=)
{
LL t=a;
a=b;
b=t%b;
}
return a;
} void dp()
{
if(k==)
{
puts("");
LL tmp =0x3f3f3f3f3f3f3f3f, ans=-;
for (int i = ; i<=n;++i)
if (a[i]<=tmp)
{
ans=i;
tmp=a[i];
}
printf("%lld\n", ans);
return;
}
for(int j=;j<s;j++) f[][j]=make_pair(n+,);
for(int i=;i<=n;i++)
{
for (int j = ; j < s; ++j)
{
f[i][j] = f[i - ][j];
int pre = key[v[j] / gcd(v[j], b[i])];
f[i][j]=min(f[i][j], make_pair(f[i - ][pre].first + , f[i - ][pre].second + a[i]));
}
}
if (f[n][s-].first > n) puts("-1");
else
{
printf("%d\n", f[n][s-].first);
for (int i = n; i; --i)
{
if (f[i][key[k]] != f[i - ][key[k]])
{
printf("%d ", i);
k /= gcd(k, b[i]);
}
}
puts("");
}
} int main()
{
//freopen("D:\\input.txt","r",stdin);
while(~scanf("%d%lld",&n,&k))
{
LL m=sqrt(k+0.5);
v.clear();
for(int i=;i<=m;i++)
{
if(k%i==)
{
v.push_back(i);
if(k/i!=i) v.push_back(k/i);
}
}
sort(v.begin(),v.end());
s=v.size();
key.clear();
for(int i=;i<s;i++) key[v[i]]=i;
for(int i=;i<=n;i++)
{
scanf("%lld",&a[i]);
b[i]=gcd(k,a[i]);
}
dp();
}
return ;
}

Codeforces Round #365 (Div. 2) E - Mishka and Divisors(转化成01-背包)的更多相关文章

  1. Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum 离线+线段树

    题目链接: http://codeforces.com/contest/703/problem/D D. Mishka and Interesting sum time limit per test ...

  2. Codeforces Round #365 (Div. 2)-D Mishka and Interesting sum(树状数组)

    题目链接:http://codeforces.com/contest/703/problem/D 思路:看了神犇的代码写的... 偶数个相同的数异或结果为0,所以区间ans[l , r]=区间[l , ...

  3. Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum (离线树状数组+前缀xor)

    题目链接:http://codeforces.com/contest/703/problem/D 给你n个数,m次查询,每次查询问你l到r之间出现偶数次的数字xor和是多少. 我们可以先预处理前缀和X ...

  4. Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(离线树状数组)

    http://codeforces.com/contest/703/problem/D 题意: 给出一行数,有m次查询,每次查询输出区间内出现次数为偶数次的数字的异或和. 思路: 这儿利用一下异或和的 ...

  5. Codeforces Round #365 (Div. 2) B - Mishka and trip

    http://codeforces.com/contest/703/problem/B 题意: 每个点都有一个值,每条边的权值为这两个点相乘.1~n成环.现在有k个城市,城市与其他所有点都相连,计算出 ...

  6. Codeforces Round #365 (Div. 2) D.Mishka and Interesting sum 树状数组+离线

    D. Mishka and Interesting sum time limit per test 3.5 seconds memory limit per test 256 megabytes in ...

  7. Codeforces Round #365 (Div. 2) D.Mishka and Interesting sum

    题目链接:传送门 题目大意:给n个数,m次询问,每次询问区间 l,r 内出现偶数次数的异或和 题目思路:前缀和+离线处理+树状数组 首先可以知道, l,r 内出现奇数次的数的和,就是把 l,r内所有数 ...

  8. Codeforces Round #360 (Div. 2) E. The Values You Can Make 01背包

    题目链接: 题目 E. The Values You Can Make time limit per test:2 seconds memory limit per test:256 megabyte ...

  9. Codeforces Round #365 (Div. 2) C - Chris and Road 二分找切点

    // Codeforces Round #365 (Div. 2) // C - Chris and Road 二分找切点 // 题意:给你一个凸边行,凸边行有个初始的速度往左走,人有最大速度,可以停 ...

随机推荐

  1. SpringBoot 之数据访问

    1. Spring Boot 与 JDBC 默认使用 org.apache.tomcat.jdbc.pool.DataSource 数据源; // application.yml spring: da ...

  2. spring Bean装配的几种方式简单介绍

    Spring容器负责创建应用程序中的bean同时通过ID来协调这些对象之间的关系.作为开发人员,我们需要告诉Spring要创建哪些bean并且如何将其装配到一起. spring中bean装配有两种方式 ...

  3. (转)MFC中Doc,View,MainFrmae,App各指针的互相获取

    App是应用域,所有的域中的东西都可以通过全局函数访问到它. MainFrame是主框架,也基本可以用全局函数访问到. MainFrame下是若干个ChildFrame,ChildFrame中若干个V ...

  4. Teleport Ultra 垃圾代码 tppabs的清理<转>

    在使用整站下载软件Teleport Pro或Teleport Ultra下载的离线文件里会包含大量垃圾代码,下载后就需要清除整站下载文件中的冗余代码:tppabs等.这些代码本是Teleport自动添 ...

  5. linux meta 18.0.1 系统安装nodejs

    前置条件是:需要准备sudo apt-get 命令 第一步: 执行命令sudo apt-get install nodejs 即可安装, 之后可使用node -v 查看版本node 版本号 第二步: ...

  6. 无密码ssh操作步骤备忘

    需求:A机器无密码登陆到B机器 1.A机器执行   ssh-keygen -t rsa  ,在~/.ssh/下生成id_rsa 和  id_rsa.pub两个文件,其中id_rsa.pub是公匙 2. ...

  7. IDEA 编译报错: 未结束的字符串文字

    最近在搞新项目,同事用的eclipse开发,而我用的是ide,项目初始是由同事创建的,项目编码是UTF-8,而我开发的ide工具默认是GBK编码,导致在编译的时候报错: 未结束的字符串文字 这个问题就 ...

  8. Javascript中的函数数学运算

    1.Math函数与属性使用语法 Math.方法名(参数1,参数2,...); Math.属性; 说明 Math函数可以没有参数,比如Math.random()函数,或有多个参数,比如Math.max( ...

  9. Linux学习笔记之Linux启动引导过程

    早期时,启动一台计算机意味着要给计算机喂一条包含引导程序的纸带,或者手工使用前端面板地址/数据/控制开关来加载引导程序.尽管目前的计算机已经装备了很多工具来简化引导过程,但是这一切并没有对整个过程进行 ...

  10. Windows Update error 80070003

    上次更新完成一半,这次更新便会出错.办法:删除上次更新残余文件. 删除Windows 用于标识计算机更新的临时文件.需要先停止Windows Update 服务: 在开始菜单的“搜索程序和文件”框输入 ...