【bzoj2257】[Jsoi2009]瓶子和燃料 扩展裴蜀定理+STL-map

最大公约数问题求解
本文介绍了一种基于扩展裴蜀定理与STL-map的数据结构算法,用于解决从n个瓶子中选择k个,使这些瓶子能组合出的最大最小体积(即最大公约数)的问题。通过枚举所有数的约数并利用map进行维护,实现高效求解。

题目描述

给出 $n$ 个瓶子和无限的水,每个瓶子有一定的容量。每次你可以将一个瓶子装满水,或将A瓶子内的水倒入B瓶子中直到A倒空或B倒满。从中选出 $k$ 个瓶子,使得能够通过这 $k$ 个瓶子凑出的最小体积最大。求这个体积。

输入

第1行:2个整数N,K,  
第2..N 行:每行1个整数,第i+1 行的整数为Vi  

输出

仅1行,一个整数,表示火星人给出燃料的最大值。

样例输入

3 2 


4

样例输出

4


题解

扩展裴蜀定理+STL-map

显然通过容量为 $v_1,v_2,...,v_k$ 的瓶子能够凑出的容量 $c$ 满足:$v_1x_1+v_2x_2+...+v_kx_k=c$ 存在整数解。

根据裴蜀定理有 $\gcd(v_1,v_2,...,v_k)|c$ 。因此最小正整数就是它们的 $\gcd$ 。

原问题转化为:从 $n$ 个数中选出 $k$ 个,使得它们的 $\gcd$ 最大。

枚举所有数的所有约数,判断其是否是至少 $k$ 个数的约数,并更新答案即可。这个过程可以使用STL-map维护。

时间复杂度 $O(n\sqrt v+n\log n·约数个数)$ ,由于约数个数极少,远达不到 $\sqrt v$ ,因此可以通过。

#include <map>
#include <cstdio>
using namespace std;
map<int , int> mp;
map<int , int>::iterator it;
int main()
{
	int n , k , i , j , x , ans = 0;
	scanf("%d%d" , &n , &k);
	for(i = 1 ; i <= n ; i ++ )
	{
		scanf("%d" , &x);
		for(j = 1 ; j * j <= x ; j ++ )
		{
			if(x % j == 0)
			{
				mp[j] ++ ;
				if(j * j != x) mp[x / j] ++ ;
			}
		}
	}
	for(it = mp.begin() ; it != mp.end() ; it ++ )
		if(it->second >= k)
			ans = max(ans , it->first);
	printf("%d\n" , ans);
	return 0;
}

 

转载于:https://www.cnblogs.com/GXZlegend/p/8610437.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值