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 )

括号中能构成任意一个整数, 当G=1时才能使得ax+by 能组成1。

然后就是动态维护集合中每个gcd对应的最小花费。

#include <cstdio>
#include <cstring>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <map>
using namespace std;
int l[306];
int c[306];
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
map<int,int>mp[2];
map<int,int>::iterator it;
int pre,cur;
int hehe; int papa;
void setMin(int x,int y)
{
    if(mp[cur].count(x))
    {
        if(y<mp[cur][x])
            mp[cur][x]=y;
    }
    else mp[cur][x]=y;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&l[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&c[i]);
    pre=0;cur=1;
    mp[0][l[1]]=c[1];
    for(int i=2;i<=n;i++)
    {
        mp[cur].clear();
        mp[cur][l[i]]=c[i];
        for(it=mp[pre].begin();it!=mp[pre].end();it++)
        {
            int x=it->first;
            int y=it->second;
            setMin(x,y);
            setMin(gcd(x,l[i]),y+c[i]);
        }
        swap(pre,cur);
    }
    if(!mp[pre].count(1))
        puts("-1");
    else
        printf("%d\n",mp[pre][1]);
}
时间: 2024-07-28 17:42:59

Codeforces 512B Fox And Jumping dp+gcd的相关文章

[Codeforces#510D] Fox And Jumping

Codeforces题号:#510D 出处: Codeforces 主要算法:贪心+优先队列 难度:4.6 思路分析: 题意:给出n张卡片,分别有l[i]和c[i].在一条无限长的纸带上,你可以选择花c[i]的钱来购买卡片i,从此以后可以向左或向右条l[i]个单位.购买其他卡片后,可以获得更多的跳跃单位.先要求至少花多少元钱才能够任意跳到纸带上任意一个位置.若不行,输出-1. 首先分析如果只有两个技能的情况.若这两个技能的跳跃长度有最大公约数(x),且满足(x > 1),则一定能跳到任意一个位置

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 55D Beautiful numbers 数位DP+数学

题意大概是,判断一个正整数区间内有多少个整数能被它自身的每一个非零的数字整除. 因为每一个位置上的整数集s = {0,1,2,3,4,5,6,7,8,9} lcm(s) = 2520 现在有一个整数t是由s中一个或者多个数字构成的,记为abcde,显然t = a*10^4+b*10^3+c*10^2+d*10^1+e 要使得t能被a,b,c,d,e整除,必然有t % lcm(a,b,c,d,e) = 0 因为a,b,c,d,e去重之后一定是s的一个子集,所以lcm(s)一定是lcm(a,b,c,

UESTC 923 稳住GCD DP + GCD

定义:dp[i][j] 表示 在前i个数中,使整个gcd值为j时最少取的数个数. 则有方程: gg = gcd(a[i],j) gg == j : 添加这个数gcd不变,不添加,  dp[i][j] = dp[i-1][j] gg != j: t添加,更新答案,                dp[i][gg] = dp[i-1][j] + 1 最后答案为dp[n][g] (g为原始的所有数的gcd) 时间复杂度: O(n*max(a[i])) 代码: #include <iostream>

Codeforces 360C Levko and Strings dp

题目链接:点击打开链接 题意: 给定长度为n的字符串s,常数k 显然s的子串一共有 n(n-1)/2 个 要求找到一个长度为n的字符串t,使得t对应位置的k个子串字典序>s #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<vector> #include<set> using namespace std; #

CodeForces 30C Shooting Gallery 简单dp

题目链接:点击打开链接 给定n个气球 下面n行 x y t val 表示气球出现的坐标(x,y) 出现的时刻t,气球的价值val 枪每秒移动1个单位的距离 问: 射击的最大价值,开始时枪瞄准的位置任意. 思路: dp一下.. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <math.h> #include <set

Codeforces 459E Pashmak and Graph(dp+贪心)

题目链接:Codeforces 459E Pashmak and Graph 题目大意:给定一张有向图,每条边有它的权值,要求选定一条路线,保证所经过的边权值严格递增,输出最长路径. 解题思路:将边按照权值排序,每次将相同权值的边同时加入,维护每个点作为终止点的最大长度即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 3

codeforces 149D - Coloring Brackets (区间dp)

题目大意: 给出一组合法的括号. 括号要么不涂颜色,要么就涂上红色或者绿色. 匹配的括号只能有一个有颜色. 两个相邻的括号不能有相同的颜色. 思路分析: 因为是一个合法的括号序列. 所以每个括号与之匹配的位置是一定的. 那么就可以将这个序列分成两个区间. (L - match[L] )  (match[L]+1, R) 用递归先处理小区间,再转移大区间. 因为条件的限制,所以记录区间的同时,还要记录区间端点的颜色. 然后就是一个递归的过程. #include <cstdio> #include

UVA10759 - Dice Throwing(dp+gcd)

UVA10759 - Dice Throwing(dp+gcd) 题目链接 题目大意:n个色子,求n个色子之和不小于x的概率. 解题思路:因为可以将题目转化成求n个色子和小于x的数目,最后再6^n减去就这个数目就是大于等于x的数目了.因为n最大就24,这样还是可以用long long来存放,最后输出要求的是分数形式,将分子分母用gcd约分一下输出即可. 代码: #include <cstdio> #include <cstring> typedef long long ll; co