CF851 D 枚举 思维

给出n个数,你可以对每个数把它变为0,或者增加1,分别需要花费x, y。问把所有数的GCD变为不为1的最小花费是多少。

n的范围5x1e5,a[i]的范围1e6。

开始想通过枚举最终gcd值,然后通过判左右个数以及消费来二分,显然是愚蠢的想法,因为一个数在不同模数下余数并不单调阿!

实际上是枚举gcd值,首先a[i]只有1e6范围,预处理前缀和:cnt[i]表示前a[] < i的个数和,sum[i] 比i小的所有a[]的和。

这样在枚举gcd的倍数值时,只要找到gcd范围内的一个划分,小于该划分的数的余数使用消去消费<增加该数到gcd的倍数的消费,那么只要计算gcd的所有倍数,就能得到该gcd作为最终因子的花费了。

/** @Date    : 2017-09-06 19:32:17
  * @FileName: D.cpp
  * @Platform: Windows
  * @Author  : Lweleth ([email protected])
  * @Link    : https://github.com/
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e6+20;
const double eps = 1e-8;

LL n, x, y;
LL sum[N*2], cnt[N*2];
int main()
{
	while(cin >> n >> x >> y)
	{
		MMF(cnt);
		MMF(sum);
		for(int i = 0; i < n; i++)
		{
			LL t;
			scanf("%lld", &t);
			cnt[t]++;
			sum[t] += t;
			/*if(n <= 1)
			{
				printf("%d\n", t==1?min(x,y):0);
				return 0;
			}*/
		}

		for(int i = 1; i < N*2; i++)
			cnt[i] += cnt[i - 1], sum[i] += sum[i - 1];

		LL ans = 1e16;
		for(LL i = 2; i <= 1000000; i++)
		{
			LL t = 0;
			for(LL j = i; j < 1000000 + i; j+=i)
			{
				LL ma = max(j - i + 1, j - x / y);
				t += (cnt[ma - 1] - cnt[j - i]) * x;//直接消去
				t += ((cnt[j] - cnt[ma - 1]) * j - (sum[j] - sum[ma - 1])) * y;
			}
			if(t < ans && t >= 0)
				ans = t;

		}
		printf("%lld\n", ans);
	}
    return 0;
}
时间: 2024-10-31 14:58:45

CF851 D 枚举 思维的相关文章

hdu4346 枚举思维

http://acm.hdu.edu.cn/showproblem.php?pid=4346 Problem Description There is a road from city A to city B.On the road,there are N positions(indexed from 0 to N-1).In order to celebrate the Multi-University training,the mayor of city A commands a worke

CF543B Destroying Roads 枚举 + 思维 + BFS

Code: #include <bits/stdc++.h> #define ll long long #define setIO(s) freopen(s".in","r",stdin) #define maxn 3002 using namespace std; queue<int>Q; vector<int>G[maxn]; int n,m,s1,t1,l1,s2,t2,l2; int vis[maxn],d[maxn][m

!hdu 4091--贪心、枚举--(思维)

题意:有一个容量为n的箱子,有两种珠宝,占的体积和价值分别是s1,v1,s2,v2,求能装下的最大的价值总量. 分析:刚开始以为是背包问题,但其实没那么简单:后来分情况讨论还是不行:后来又暴力枚举,当然是超时了.正确做法是有一部分是用背包的贪心,另一部分用枚举!现在就是看哪一部分用贪心. 看别人的题解是:L = LCM(s1,s2),可是知道大于L的部分就用价值比高的,所以n%L的部分枚举,其余部分贪心,不过这样可能得到的还不是最优解,所以n%L+L的部分枚举,这样就可以了,具体原因我还没想明白

计算机程序的思维逻辑 (23) - 枚举的本质

前面系列,我们介绍了Java中表示和操作数据的基本数据类型.类和接口,本节探讨Java中的枚举类型. 所谓枚举,是一种特殊的数据,它的取值是有限的,可以枚举出来的,比如说一年就是有四季.一周有七天,虽然使用类也可以处理这种数据,但枚举类型更为简洁.安全和方便. 下面我们就来介绍枚举的使用,同时介绍其实现原理. 基础 基本用法 定义和使用基本的枚举是比较简单的,我们来看个例子,为表示衣服的尺寸,我们定义一个枚举类型Size,包括三个尺寸,小/中/大,代码如下: public enum Size {

一道有意思的思维题 --- 排序、枚举

这道题是在与学弟吃饭的路上听学弟讲的,感觉挺有意思的,需要不少的思维(可能我长时间没有刷题了,有点笨了~) 特此记录一下: Problem: 有n个(x,y)元组,求从中取出k个元组,使得这k个元组的x之和乘以其中最小的y值的值最大 ( sum(x)*min(y) in k个元组 ) Solution: 将n个元组按照y值从小到大排序,然后从小到大枚举每个y值,以当前的y值为选取的k个元组中的最小值,那么k个元组位于当前元组之后(一定包含当前元组).也就是说,有k-1个元组还未确定,需要从当前元

HDU 1172.猜数字【思路转换,思维练习】【枚举】【8月8】

猜数字 Problem Description 猜数字游戏是gameboy最喜欢的游戏之一.游戏的规则是这样的:计算机随机产生一个四位数,然后玩家猜这个四位数是什么.每猜一个数,计算机都会告诉玩家猜对几个数字,其中有几个数字在正确的位置上. 比如计算机随机产生的数字为1122.如果玩家猜1234,因为1,2这两个数字同时存在于这两个数中,而且1在这两个数中的位置是相同的,所以计算机会告诉玩家猜对了2个数字,其中一个在正确的位置.如果玩家猜1111,那么计算机会告诉他猜对2个数字,有2个在正确的位

Educational Codeforces Round 61 (Rated for Div. 2)F(区间DP,思维,枚举)

#include<bits/stdc++.h>typedef long long ll;const int inf=0x3f3f3f3f;using namespace std;char b[507];int dp[507][507];int main(){    memset(dp,0x3f,sizeof(dp));    int n;    scanf("%d",&n);    scanf("%s",b+1);    for(int i=1;

一道有意思的思维题2 --- 排序、枚举

这道题是又一次在和学弟吃饭的路上听学弟讲的,感觉挺不错的^_^,这样仿佛经常听学弟讲题能收获不少呀,可能明年笔试有望了,哈哈~ Problem: 平面上给了有n个人,位置由(x,y)元组给定,平面上还有m扇门,位置由(x,y)给定.现在约定每扇门只能进一个人,且人只能向左和下移动(向x-1和y-1移动),请问最多有多少人进门? Solution: 将人和门按x值从大到小排序,枚举门.对于当前枚举的门i,将值大于door[i].x的所有人的y值放入set中,找到大于等于door[i].y的最小值,

codeforces 493C Vasya and Basketball (枚举+模拟+思维)

C. Vasya and Basketball time limit per test 2 seconds memory limit per test 256 megabytes Vasya follows a basketball game and marks the distances from which each team makes a throw. He knows that each successful throw has value of either 2 or 3 point