[Codeforces#510D] Fox And Jumping

Codeforces题号:#510D

出处: Codeforces

主要算法:贪心+优先队列

难度:4.6

思路分析:

  题意:给出n张卡片,分别有l[i]和c[i]。在一条无限长的纸带上,你可以选择花c[i]的钱来购买卡片i,从此以后可以向左或向右条l[i]个单位。购买其他卡片后,可以获得更多的跳跃单位。先要求至少花多少元钱才能够任意跳到纸带上任意一个位置。若不行,输出-1.

  首先分析如果只有两个技能的情况。若这两个技能的跳跃长度有最大公约数(x),且满足(x > 1),则一定能跳到任意一个位置。比如(x = 2),那么所有奇数的格子都是跳不到的。如果(x = 3),那么所有非3的倍数都是跳不到的。因此我们可以得到结论,当且仅当(x = 1)时才能够跳到所有的地方。

  联系到多种技能的情况,若所有技能的跳跃长度的最大公约数大于1,那么就像刚才那样一定有格子跳不到。因此要求所选技能的最大公约数必须为1。因此题目可以转化为从n个技能中选取几个,使得其最大公约数为1,并且要让花费尽量小。

  这就可以联系到dp了。令f[i]表示选择一些数并且最大公约数为i时的最小花费。很明显答案就是f[1]。转移也很简单,先扫描1~n,在扫描所有可能的最大公约数j。求出j与l[i]的最小公约数tmp。利用f[j]就可以转移f[tmp]了。(用与不用f[i])

  然而第9个点RE了。

  回想一下过程,由于(l[i] <= 10^9),所以f数组很明显装不下了。可以n只有300,300个卡片能有多少个最大公约数啊。于是我们联想到了map,把f改成一个map就解决问题了。

代码注意点:

  注意f数组的初始化,f[0]=0,不然就永远进不去循环了……

Code

/** This Program is written by QiXingZhi **/
#include <cstdio>
#include <map>
#include <queue>
#include <cstring>
#include <algorithm>
#define  r  read()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int N = 310;
const int INF = 1061109567;
inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ ‘-‘ && (c < ‘0‘ || c > ‘9‘)) c = getchar();
    if(c == ‘-‘) w = -1, c = getchar();
    while(c >= ‘0‘ && c <= ‘9‘) x = (x << 3) +(x << 1) + c - ‘0‘, c = getchar();
    return x * w;
}
int n,tmp;
int L[N],c[N];
map <int, int> f;
int Gcd(int a, int b){
    if(a < b) return Gcd(b,a);
    if(b == 0) return a;
    return Gcd(b,a % b);
}
int main(){
//    freopen(".in","r",stdin);
    n = r;
    for(int i = 1; i <= n; ++i){
        L[i] = r;
    }
    for(int i = 1; i <= n; ++i){
        c[i] = r;
    }
    f[0] = 0;
    for(int i = 1; i <= n; ++i){
        map <int,int> :: iterator it = f.begin();
        for(; it != f.end(); ++it){
            tmp = Gcd(L[i], it->first);
            if(f[tmp] != 0){
                f[tmp] = Min(f[tmp], it->second + c[i]);
            }
            else{
                f[tmp] = it->second + c[i];
            }
        }
    }
    if(f.count(1)){
        printf("%d",f[1]);
    }
    else{
        printf("-1");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/qixingzhi/p/9305782.html

时间: 2024-11-14 05:41:39

[Codeforces#510D] Fox And Jumping的相关文章

Codeforces 512B Fox And Jumping dp+gcd

题目链接:点击打开链接 题意: 给定n个数 下面2行是n个数字和购买该数字的花费. 使得购买的数字能通过加减获得任意一个正整数.问最小的花费是多少.(购买得到的数字可以多次使用) 思路: 首先是要获得任意的正整数,其实就是获得1就可以了. 而获得1的话 只需要我们选的数的gcd = 1即可. 设 有整数x,y,要使得x y能构造任意一个整数,充要条件就是gcd(x, y)=1 推论: 设int G = gcd(x, y); 则 ax+by = G( ax/G+by/G ) 括号中能构成任意一个整

Fox And Jumping

Fox And Jumping 题目链接:http://codeforces.com/problemset/problem/512/B dp 若所选卡片能到达区间内任意点,那么所选卡片的最大公约数为1(a*x+b*y=gcd(a,b)=1). 定义状态dp[i]:获得i需要的最小的代价. 代码如下: 1 #include<cstdio> 2 #include<map> 3 #include<iostream> 4 #define LL long long 5 using

【Codeforces 290 B】Fox And Jumping

根据裴蜀定理,当且仅当选出来的集合的L[i]的gcd等于1时,才能表示任何数. 考虑普通的dp,dp[i][j]表示前i个数gcd为j的最少花费,j比较大,但状态数不多,拿个map转移就好了. 技巧&套路: 裴蜀定理,gcd为1表示任何数. 当状态数不多的时候,map暴力转移dp. 1 #include <cstdio> 2 #include <map> 3 #include <algorithm> 4 5 const int N = 305; 6 7 int

CodeForces 388A Fox and Box Accumulation (模拟)

A. Fox and Box Accumulation time limit per test:1 second memory limit per test:256 megabytes Fox Ciel has n boxes in her room. They have the same size and weight, but they might have different strength. The i-th box can hold at most xi boxes on its t

CodeForces 510E Fox And Dinner

CodeForces 510E 素数打表+最大流+最大流打印路径 注意到ai (2 ≤ ai ≤ 104).那么题中的所有素数一定是一个奇数和一个偶数的和.那么所有的桌子都是偶环 将所有的偶数点连接超级源点,奇数点连接超级汇点,容量都为2.将所有的偶数点与奇数点间建容量为1的边,若满流,则可以满足条件 画个图可以知道这样建图是正确的→_→,怎么能想到这一点呢?弱不造 #include<cstdio> #include<cstring> #include<algorithm&g

CodeForces 388A Fox and Box Accumulation 贪心

Fox Ciel has n boxes in her room. They have the same size and weight, but they might have different strength. The i-th box can hold at most xi boxes on its top (we'll call xi the strength of the box). Since all the boxes have the same size, Ciel cann

codeforces 510B. Fox And Two Dots 解题报告

题目链接:http://codeforces.com/problemset/problem/510/B 题目意思:给出 n 行 m 列只有大写字母组成的字符串.问具有相同字母的能否组成一个环. 很容易知道要用到深搜.暴力搜索--- 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 cons

codeforces 510C Fox And Names 拓扑排序

传送门:cf 510D 给定n个字符串,问能否存在这样的字母表,使得字符串的排序满足字典序.即依据新的字母表,排序满足字典序大小. 假设满足字典序,则我们可以依据已有的字符串得出各字母之间的大小关系,然后通过拓扑排序来判断是否存在可行解,输出任意解,因此只需要判断是否存在解即可. /****************************************************** * File Name: a.cpp * Author: kojimai * Create Time: 2

Codeforces 371BB. Fox Dividing Cheese

Two little greedy bears have found two pieces of cheese in the forest of weight a and b grams, correspondingly. The bears are so greedy that they are ready to fight for the larger piece. That's where the fox comes in and starts the dialog: "Little be