首页 > 代码库 > Codeforces 512B Fox And Jumping dp+gcd

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]);
}


Codeforces 512B Fox And Jumping dp+gcd