题目链接

题目

见链接。

题解

方法一

知识点:背包dp,STL。

题目意思是让我们判断能否从这些数中选出一些数使得选的数公共gcd为 \(1\),如果可以输出最小花费。

一眼背包dp,但要map超大背包优化,因为数字很大 \(10^9\) ,显然无法直接在第二维放下。

设 \(dp[i][j]\) 表示考虑到第 \(i\) 个数,所有数的gcd为 \(j\) 的情况。 因为用map优化了,没法填表了,因为每行都的元素都不确定,应该用刷表法,用这一行结果推到下一行。转移方程为:

\[\begin{aligned}
dp[i][x] &= \min(dp[i-1][x],dp[i][x])\\
dp[i][gcd(l[i],x)] &= \min(dp[i-1][x] + c[i],dp[i][gcd(l[i],x)])
\end{aligned}
\]

前者表示不选第 \(i\) 个数的转移,后者表示选了第 \(i\) 个数的转移。

因为不能 memset 初始化正无穷,因此要做到循环中对第一次出现的状态初始化。同时,这也是解决数组太大每次全部初始化很费时间情况下的一种技巧。

注意为了方便,初始化了 \(dp[0][0] = 0\) 。用于每次选一个数自己是第一个数的情况,能正确被标记而不用特判,即 \(gcd(l[i],0) = l[i]\)。因为在我们写的gcd函数里, \(0\) 可以当作特殊的单位元,特殊之处在于其应该出现在函数的后面一个位置,即 \(gcd(a,0)\) ,否则会出错。

时间复杂度 \(O(n*玄学)\) ,qwq最大公约数种类不知道怎么算

空间复杂度 \(O(玄学)\)

方法二

知识点:BFS,优先队列,记忆化搜索。

说白了就是记忆化搜索,用广搜做最短路,求花费最小的路径,因此用优先队列。细节处理比dp少一点,而且差不多。

时间复杂度 \(O(能过而且更快)\)

空间复杂度 \(O(能过)\)

代码

方法一

///满足最优子结构,顺序上没有后效性可以dp
#include <bits/stdc++.h> using namespace std; int l[307], c[307];
unordered_map<int, int> dp[307]; int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1;i <= n;i++) cin >> l[i];
for (int i = 1;i <= n;i++) cin >> c[i];
dp[0][0] = 0;///gcd单位元
for (int i = 1;i <= n;i++) {
for (auto [x, y] : dp[i - 1]) {///向后传递,不能写找前继承
if (!dp[i].count(x)) dp[i][x] = 0x3f3f3f3f;
dp[i][x] = min(dp[i][x], y);
int d = gcd(l[i], x);
if (!dp[i].count(d)) dp[i][d] = 0x3f3f3f3f;
dp[i][d] = min(dp[i][d], y + c[i]);
}
}
if (dp[n].count(1)) cout << dp[n][1] << '\n';
else cout << -1 << '\n';
return 0;
}

方法二

///也可以写成优先队列bfs,好处是不用考虑后效性,以花费从小到大为顺序扩展,复杂度玄学
#include <bits/stdc++.h> using namespace std; int n;
int l[307], c[307];
unordered_set<int> vis;
struct node {
int l;
int c;
friend bool operator<(const node &a, const node &b) {
return a.c > b.c;
}
}; int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
} int bfs() {
priority_queue<node> pq;
pq.push({ 0,0 });
while (!pq.empty()) {
node cur = pq.top();
pq.pop();
if (cur.l == 1) return cur.c;
if (vis.count(cur.l)) continue;
vis.insert(cur.l);///经过后再锁
for (int i = 1;i <= n;i++) {
int d = gcd(l[i], cur.l);
if (vis.count(d)) continue;
pq.push({ d,cur.c + c[i] });
}
}
return -1;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1;i <= n;i++) cin >> l[i];
for (int i = 1;i <= n;i++) cin >> c[i];
cout << bfs() << '\n';
return 0;
}

CF510D Fox And Jumping的更多相关文章

  1. Codeforces Round #290 (Div. 2) D. Fox And Jumping dp

    D. Fox And Jumping 题目连接: http://codeforces.com/contest/510/problem/D Description Fox Ciel is playing ...

  2. Fox And Jumping

    Fox And Jumping 题目链接:http://codeforces.com/problemset/problem/512/B dp 若所选卡片能到达区间内任意点,那么所选卡片的最大公约数为1 ...

  3. CodeForces - 512B Fox And Jumping[map优化dp]

    B. Fox And Jumping time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  4. Codeforces510 D. Fox And Jumping

    Codeforces题号:#510D 出处: Codeforces 主要算法:map+DP 难度:4.6 思路分析: 题意:给出n张卡片,分别有l[i]和c[i].在一条无限长的纸带上,你可以选择花c ...

  5. 【Cf #290 B】Fox And Jumping(dp,扩展gcd)

    根据裴蜀定理,当且仅当选出来的集合的L[i]的gcd等于1时,才能表示任何数. 考虑普通的dp,dp[i][j]表示前i个数gcd为j的最少花费,j比较大,但状态数不多,拿个map转移就好了. $ \ ...

  6. 【codeforces 510D】Fox And Jumping

    [题目链接]:http://codeforces.com/contest/510/problem/D [题意] 你可以买n种卡片; 每种卡片的花费对应c[i]; 当你拥有了第i种卡片之后; 你可以在任 ...

  7. Codeforces 512B: Fox And Jumping

    题目链接 题意说的是,有n种卡片,使用第i种卡片可以使当前自己在数轴上的位置移动 l[i],要获得使用第i种卡片的代价是 c[i],求能使自己移动到数轴上任意位置的最小代价,如果不可能则输出-1 当前 ...

  8. CF习题集三

    CF习题集三 一.CF8C Looking for Order 题目描述 \(Lena\)喜欢秩序井然的生活.一天,她要去上大学了.突然,她发现整个房间乱糟糟的--她的手提包里的物品都散落在了地上.她 ...

  9. 数论专项复习(一)扩展欧几里得算法(exgcd)

    简介 扩展欧几里得算法(简称扩欧,exgcd),用来求下列方程的一组解: \[ax+by=(a,b) \] 算法介绍 1. 裴蜀定理 裴蜀定理(Bézout's lemma):若 \(a\in \ma ...

  10. CodeForces Round #290 Div.2

    A. Fox And Snake 代码可能有点挫,但能够快速A掉就够了. #include <cstdio> int main() { //freopen("in.txt&quo ...

随机推荐

  1. 基于python+django的电影搜索网站-搜索引擎系统设计与实现

    该项目是基于python的web类库django开发的一套web网站,给师弟做的课程设计. 本人的研究方向是一项关于搜索的研究项目.在该项目中,笔者开发了一个简单版的搜索网站,实现了对数据库数据的检索 ...

  2. Verilog仿真实践

    Verilog必须掌握 逻辑仿真工具(VCS)和逻辑综合工具(DC) AndOR module AndOr( output X,Y, input A,B,C ); // A B进行按位与运算 assi ...

  3. 【SHELL】百分比进度指示,原地踏步

    百分比进度指示,原地踏步效果实现主要利用退格'\b',同行'\c' #!/bin/bash function percentage_progress() { progress=$(($1*100/$2 ...

  4. 【lvgl-micropython】官方源码之ports/unix 编译报错

    lv_micropython/ports/unix make 报错 编译环境如下 这是缺少SDL2库导致的 sudo apt-get install libsdl2-2.0 sudo apt-get ...

  5. 函数指针、std::function、std::bind

    函数指针.std::function.std::bind 函数指针: C++语法中可以直接将函数名作为指针, void fun(int a, int b); 在这个函数声明中,函数指针即为fun,传入 ...

  6. ONVIF网络摄像头(IPC)客户端开发—ONVIF介绍

    ​ 1.前言: 网上已经有很多关于ONVIF开发的资料,这里概括介绍一下ONVIF协议以及介绍一下我自己在开发ONVIF网络摄像头的一些流程和经验,做个开发记录和经验总结,以备将来查看,也可供他人参考 ...

  7. VMto阿里云的简单过程

    VMto阿里云的简单过程 第一步打开网站 https://smcnext.console.aliyun.com/sourceServers/importMigrationSource?spm=5176 ...

  8. [转帖]容器环境的JVM内存设置最佳实践

    https://cloud.tencent.com/developer/article/1585288 Docker和K8S的兴起,很多服务已经运行在容器环境,对于java程序,JVM设置是一个重要的 ...

  9. [转帖]记druid 连接池没满,但超时问题 GetConnectionTimeoutException active 5, maxActive 100

    记druid 连接池没满,但超时问题 GetConnectionTimeoutException active 5, maxActive 100 问题说明 线上服务突然出现报错,通过日志查找发现是因为 ...

  10. [转帖]Centos使用chrony做时间同步

    https://www.cnblogs.com/lizhaoxian/p/11260041.html Chrony是一个开源的自由软件,在RHEL 7操作系统,已经是默认服务,默认配置文件在 /etc ...