题目背景

HJZ 有很多玩具。他最喜欢玩的玩具是一个可以变化的数组。

题目描述

HJZ 的数组初始时有 n 个元素。他可以把一个位置上的数加上或减去一个固定的

数 x。

一天 LJZ 和 HZY 来 HJZ 家玩。LJZ 突发奇想,提出了一个问题:如何在给定的

操作步数内最小化数组所有元素的乘积呢?

HJZ 百思不得其解,但是他想博得 HZY 的好感,就把这个问题交给你啦 ~

由于最小乘积可能很小,HJZ 只需要你给出

. 最 . 小 . 乘 . 积 . 对 10^9 + 7

. 取 . 模的结果。

. 请 . 注 . 意 . 一 . 个 . 数 . 对 p . 取 . 模 . 的 . 结 . 果 . 一 . 定 . 是 . 非 . 负 . 数, . 即 . 你 . 输 . 出 . 的 . 结 . 果 ans

. 要 . 满 . 足 0 ≤ ans < 10^ 9 + 7 。

输入输出格式

输入格式:

从文件 array.in 中读入数据。

第一行三个整数 n,k, x 分别表示数组元素个数、最多操作次数和每次操作的数。

第二行 n 个整数 a 1 ,a 2 ,...,a n 表示数组初始时的元素。

输出格式:

输出到文件 array.out 中。

一行一个在 [0,10 9 + 7) 范围内的整数,表示最小乘积的绝对值对 10 9 + 7 取模的

结果。

输入输出样例

输入样例#1:

3 2 7
5 4 2
输出样例#1:

999999732
【样例 1 解释】
最多可以进行两次操作,每次把一个位置 +7 或 −7 。
最优策略是将数组第二个元素 +7 ,第三个元素 −7 ,得到新的数组 5 11 − 5 ,乘
积为 5 × 11 × (−5) = −275 ,模 10 9 + 7 的结果是 999999732 。
输入样例#2:

5 3 1
5 4 3 5 5
输出样例#2:

0
【样例 2 解释】
只能把一个位置 +3 或 −3 ,把第三个位置 −3 最优,乘积为 0 。
【子任务】
对于所有测试点,1 ≤ n,k ≤ 2 × 10^5 ,1 ≤ x ≤ 10^9 ,|a i | ≤ 10^9 。
分析:数据很大,不可能dp,稍微做过一点贪心题的人能够一眼看出这道题就是用贪心做,但是具体怎么贪心比较难想,如果我们能让乘积变成负数是最好的,如果当前的乘积是正数,那么我们要先用最少的步数让乘积变成负数,这个时候操作绝对值最小的数让它变成符号相反的数就能使乘积变成负数了.
要使每次操作的贡献最大,肯定是操作绝对值最小的数,如果绝对值最小的数是正数,就让他增加x,否则就让它减少x,乘积还是负数,而且每一次的贡献是最大的,所以答案一定是最优的,每次找绝对值最小的数用优先队列.
需要注意对于0的处理.
#include <cstdio>
#include <functional>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cmath> using namespace std; const long long mod = ; long long n, k, x,ans = ,cnt;
priority_queue <long long> q1; //存负数
priority_queue <long long, vector<long long>, greater<long long> >q2; //存正数 void jian()
{
long long y = q2.top();
q2.pop();
while (k && y)
{
k--;
y -= x;
if (y <= )
{
q1.push(y);
return;
}
}
q2.push(y);
} void jia()
{
long long y = q1.top();
q1.pop();
while (k && y <= )
{
k--;
y += x;
if (y > )
{
q2.push(y);
return;
}
}
q1.push(y);
} int main()
{
scanf("%lld%lld%lld", &n, &k, &x);
for (int i = ; i <= n; i++)
{
long long t;
scanf("%lld", &t);
if (t <= )
{
q1.push(t);
cnt++;
}
else
q2.push(t);
}
//先让乘积变成负数
if (cnt % == )
{
if (cnt == )
jian();
else
if (cnt == n)
jia();
else
if (abs(q1.top()) < abs(q2.top()))
jia();
else
jian();
}
for (int i = ; i <= k; i++)
{
long long t1, t2;
if (!q1.empty())
t1 = q1.top();
else
t1 = -; if (!q2.empty())
t2 = q2.top();
else
t2 = ;
if (abs(t1) > abs(t2))
{
q2.pop();
t2 += x;
q2.push(t2);
}
else
{
q1.pop();
t1 -= x;
q1.push(t1);
}
}
while (!q1.empty())
{
ans = (ans * (q1.top() % mod)) % mod;
q1.pop();
}
while (!q2.empty())
{
ans = (ans * (q2.top() % mod)) % mod;
q2.pop();
}
while (ans < )
ans += mod;
printf("%lld\n", ans); return ;
}


常州模拟赛d7t2 数组的更多相关文章

  1. 常州模拟赛d7t3 水管

    分析:第一问还是很好做的,关键是怎么做第二问.我们可以每次删掉最小生成树上的一条边,然后再求一次最小生成树,看边权和大小和原来的是不是一样的,不过这个做法效率很低. 考虑Kruskal算法的原理,每次 ...

  2. 常州模拟赛d6t3 噪音

    FJ有M个牛棚,编号1至M,刚开始所有牛棚都是空的.FJ有N头牛,编号1至N,这N头牛按照编号从小到大依次排队走进牛棚,每一天只有一头奶牛走进牛棚.第i头奶牛选择走进第p[i]个牛棚.由于奶牛是群体动 ...

  3. 常州模拟赛d5t2 mogician

    分析:一个暴力的思想是枚举g,然后枚举每个数ai,看能不能符合要求,这样复杂度是O(nA)的,直接T掉了.也没什么其他的办法了,在暴力的基础上优化一下,优化的关键是要如何快速统计出不满足要求的数的个数 ...

  4. 常州模拟赛d4t3 字符串划分

    题目描述 给你一串由小写字母组成的字符串,希望你把它划分成一些小段,使得每一小段字符串中的字母 都不相同,并且希望分的段数尽量少. 然后,把这些小段按字典序排序后输出,中间由一个空格分隔. 例如:字符 ...

  5. 常州模拟赛d4t1 立方体

    题目描述 立方体有 6 个面,每个面上有一只奶牛,每只奶牛都有一些干草.为了训练奶牛的合作精神,它 们在玩一个游戏,每轮:所有奶牛将自己的干草分成 4 等份,分给相邻的 4 个面上的奶牛. 游戏开始, ...

  6. 常州模拟赛d3t3 两只怪物心心相印

    题目背景 从前我是一位无名的旅人,旅途中我得到了某样东西:贤者之石.我因此得到悠久的时光和漂泊的生命.1897年冬天,我一时兴起舍弃了旅人的生活. 贤者之石创造出来的,是货真价实的黄金.我的名声传遍了 ...

  7. 常州模拟赛d2t2 小X的密室

    题目描述 密室中有 N 个房间,初始时,小 X 在 1 号房间,而出口在 N 号房间. 密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会 单向地 创造一条从房间 X 到房间 Y 的通道.另 ...

  8. 常州模拟赛d8t2 绘画

    分析:考虑记录每个坐标上每个颜色出现了几次,并由此算出每个颜色在这个坐标上的贡献.答案肯定是原图的答案扣去矩形的答案,再加上那个矩形同种颜色的贡献,这里的答案指的是Σdis.我们先要记录每个颜色在各个 ...

  9. 常州模拟赛d8t1 友好数对

    分析:其实就是问你有多少对a,b有且仅有两位不相同.我们可以先枚举这两位,对应ai枚举一位,对应bi枚举一位,如果ai^(1<<x) == bi^(1<<y),证明恰好有两位不 ...

随机推荐

  1. poj 1180:Batch Scheduling【斜率优化dp】

    我会斜率优化了!这篇讲的超级棒https://blog.csdn.net/shiyongyang/article/details/78299894?readlog 首先列个n方递推,设sf是f的前缀和 ...

  2. bzoj 1598: [Usaco2008 Mar]牛跑步【A*K短路】

    A*K短路模板,详见https://blog.csdn.net/z_mendez/article/details/47057461 算法流程: 把有向图全建成反向边,跑一遍所有点到t的最短路记为dis ...

  3. bzoj 1637: [Usaco2007 Mar]Balanced Lineup【瞎搞】

    我是怎么想出来的-- 把种族为0的都变成-1,按位置x排升序之后,s[i]表示种族前缀和,想要取(l,r)的话就要\( s[r]-s[l-1]==0 s[r]==s[l-1] \),用一个map存每个 ...

  4. 最优贸易 2009年NOIP全国联赛提高组(最短路)

    最优贸易 2009年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description [问题描述]C ...

  5. P4161 [SCOI2009]游戏

    传送门 首先这题的本质就是把\(n\)分成若干个数的和,求他们的\(lcm\)有多少种情况 然后据说有这么个结论:若\(p_1^{c_1}+p_2^{c_2}+...+p_m^{c_m}\leq n\ ...

  6. java虚拟机全集(31篇文章)

    深入理解java虚拟机系列 深入理解Java虚拟机笔记---内存区域 深入理解Java虚拟机笔记---判断对象是否存活 深入理解Java虚拟机笔记---垃圾收集算法 深入理解Java虚拟机笔记---垃 ...

  7. 状压DP UVA 11795 Mega Man's Mission

    题目传送门 /* 题意:洛克人有武器可以消灭机器人,还可以从被摧毁的机器人手里得到武器,问消灭全部机器人的顺序总数 状态压缩DP:看到数据只有16,就应该想到状压(并没有).因为是照解题报告写的,代码 ...

  8. C# 堆VS栈 值类型VS引用类型

    最近博客园上连续出现了几篇关于堆VS栈 值类型VS引用类型的文章. 一个是关于C# 堆VS栈的,深入浅出,动图清晰明了,链接如下 C#堆栈对比(Part One) C#堆栈对比(Part Two) C ...

  9. LN : leetcode 242 Valid Anagram

    lc 242 Valid Anagram 242 Valid Anagram Given two strings s and t, write a function to determine if t ...

  10. 在C语言中模仿java的LinkedList集合的使用(不要错过哦)

    在C语言中,多个数据的储存通常会用到数组.但是C语言的数组有个缺陷,就是固定长度,超过数组的最大长度就会溢出.怎样实现N个数储存起来而不被溢出呢. 学过java的都知道,java.util包里有一个L ...