【Codeforces】Codeforces Round #290 (Div. 2) D. Fox And Jumping | 暴力、map

50 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第29天,点击查看活动详情

题目链接

Problem - D - Codeforces

题目

Fox Ciel is playing a game. In this game there is an infinite long tape with cells indexed by integers (positive, negative and zero). At the beginning she is standing at the cell 0.

There are also nn cards, each card has 2 attributes: length lil_i and cost cic_i. If she pays cic_i dollars then she can apply ii-th card. After applying ii-th card she becomes able to make jumps of length lil_i, i. e. from cell xx to cell (xli)(x - l_i) or cell (x+li)(x + l_i).

She wants to be able to jump to any cell on the tape (possibly, visiting some intermediate cells). For achieving this goal, she wants to buy some cards, paying as little money as possible.

If this is possible, calculate the minimal cost.

题目大意

Fox Ciel 在玩游戏。在这个游戏中有一个数轴,她一开始站在 0 上。

游戏中还有 nn 张卡,每张卡有 2 个属性:lil_icic_i。如果她支付 cic_i 元,那么她可以买到第 ii 张卡。在使用第 ii 张卡片后,她从此就能够进行长度为 lil_i 的跳跃,即她可以从单元格 xx 跳到单元格 (xli)(x - l_i) 或单元格 (x+li)(x + l_i)

她希望能够跳到数轴上的任何整点(可以间接到达)。为了实现这个目标,她想花尽可能少的钱买一些卡。请输出 Fox Ciel 实现目标需要花多少元钱。

思路

题目等同于选若干张卡使得所有被选择的卡的 ll 属性的最大公约数为 1。

原题为能够跳到数轴上的任何整点,即对于 Fox Ciel 持有的卡的 ll 属性为 a1,a2,...,aka_1,a_2,...,a_k,我们需要满足 a1×x1+a2×x2+...+ak×xk=ca_1\times x_1+a_2\times x_2+...+a_k\times x_k=c 对任意整数 cc 有解(xx 为正表示往右跳,为负表示往左跳)。而上式有解的条件为 gcd(a1,a2,...,ak)cgcd(a_1,a_2,...,a_k)\mid c,所以 gcd(a1,a2,...,ak)=1gcd(a_1,a_2,...,a_k)=1

数字数量较少,范围为 1e9,我们可以开个 Map 记录前 ii 个数乱选一番后 gcdgcdxx 的最小花费为 mp[x]mp[x],对于第 i+1i+1 张输入的卡片遍历已有的答案,更新 mpmp。完成全部更新后 mp[1]mp[1] 即为所求。

代码

#include <stdio.h>
#include <vector>
#include <map>
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
int n,m,k;
LL a[301],c[301];
LL gcd(LL x,LL y) {return y==0?x:gcd(y,x%y);}
map<int,int> mp;
int main()
{
	int n;
	mp[0]=0;
	scanf("%d",&n);
	for (int i=1,t;i<=n;++i) scanf("%lld",&a[i]);
	for (int i=1,t;i<=n;++i) 
	{
		scanf("%lld",&c[i]);
		for (auto v:mp)
		{
			 t=gcd(v.first,a[i]);
			 if (mp.count(t)==0||mp[t]>v.second+c[i]) mp[t]=v.second+c[i];
		}
	}
	if (mp.count(1)) printf("%d\n",mp[1]);
	else printf("-1\n");
	return 0;
}