Codeforces Round #290 (Div. 2) D

博客详细解析了Codeforces Round #290 (Div. 2) D题目的解题思路。题目要求找到gcd为1的数的组合,使函数代价最小化。利用裴蜀定理和gcd性质,通过动态规划求解最优解。文章提供了具体的算法和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Codeforces Round #290 (Div. 2) D

题目要求满足如下约束条件的元组(l1,l2,l3,…,li)(l_1,l_2,l_3,\dots,l_i)(l1,l2,l3,,li)
l1x1+l2x2+l3x3+⋯+lixi=1l_1x_1+l_2x_2+l_3x_3+\dots+l_ix_i=1l1x1+l2x2+l3x3++lixi=1
使得函数F=∑i=1nciF=\sum_{i=1}^{n}c_iF=i=1nci最小化。

说人话就是找到若干个数,它们的gcd=1且代价最小。

根据裴蜀定理,对于不全为0的整数a,b,存在整数解x,y,满足ax+by=gcd(a,b)ax+by=gcd(a,b)ax+by=gcd(a,b)

进而方程ax+by=cax+by=cax+by=c有整数解当且仅当gcd(a,b)∣cgcd(a,b)|cgcd(a,b)c

扩展:c1x1+c2x2+c3x3+..+cnxn=dc_1x_1+c_2x_2+c_3x_3+..+c_nx_n=dc1x1+c2x2+c3x3+..+cnxn=d有解当且仅当gcd(c1,c2,c3,…,cn)∣dgcd(c_1,c_2,c_3,\dots,c_n)|dgcd(c1,c2,c3,,cn)d

而找n个数的gcd可以通过两两求解。例如gcd(a1,a2,a3)=gcd(gcd(a1,a2),a3)gcd(a_1,a_2,a_3)=gcd(gcd(a_1,a_2),a_3)gcd(a1,a2,a3)=gcd(gcd(a1,a2),a3)

本题可用动态规划的方法求解,用dp[x]保存当若干个数的gcd为x时的最小代价。

代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
const int max_n=305;
ll a[max_n];
ll b[max_n];
unordered_map<ll,ll> dp;
vector<ll> v;
ll gcd(ll a,ll b)
{
	return b==0?a:gcd(b,a%b);
}
int main(void)
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	scanf("%lld",&a[i]);
	for(int i=0;i<n;i++)
	scanf("%lld",&b[i]);
	ll ans=a[0];
	for(int i=1;i<n;i++)ans=gcd(ans,a[i]);
	if(ans!=1){
		printf("-1\n");
		return 0;
	}
	dp[a[0]]=b[0];
	v.push_back(a[0]);
	for(int i=1;i<n;i++)
	{
		ll cnt=v.size();
		if(!dp[a[i]]){
			dp[a[i]]=b[i];
			v.push_back(a[i]);
		}
		else dp[a[i]]=min(dp[a[i]],b[i]);
		for(int j=0;j<cnt;j++)
		{
			ll t=gcd(v[j],a[i]);
			if(!dp[t]){
				dp[t]=dp[v[j]]+b[i];
				v.push_back(t);
			}
			else dp[t]=min(dp[t],dp[v[j]]+b[i]);
		}
	}
	printf("%lld\n",dp[1]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值