洛谷P3543 [POI2012] WYR-Leveling Ground
题目描述
给定 \(n\) 个数和 \(a,b\) 每次可以选择一段区间 \(+a,-a,+b ,或 -b\),问最少操作几次能把它们都变成 \(0\)。如果无解请输出 \(-1\)。
样例输入
5 2 3
1 2 1 1 -1
5
分析
对于区间修改是很麻烦的,为了简化复杂度,这里可以将数组转化为差分数组以降低难度,对于每一个数,我们实际上都可以找
出一个方程 \(0+ax+by=c\) 这里的 \(c\) 实际上就是原序列数,看着是不是很眼熟,没错,就是扩展欧几里得定理,这里的\(x,y\)
指的是对 \(a,b\) 进行的操作,一次\(+a,-a\) , \(+b,-b\),互相抵消,所以肯定不是最优解,可以不考虑,那会不会出现一个数两边
的区间减去一个数,但这个数不用减的情况呢,因为这里使用的是差分数组进行的操作,进行的是单点修改,在每一个点的修改
对区间的影响是与之前点的修改相关的,每一个点的加减组合起来就完成了对于所有区间的遍历,所以这种情况也会被考虑在内
因为一次对一个数的部分操作 \(x\) , \(y\) 是对其他数操作时对这个数的影响,所以一次操作被算了两遍,所以最后答案实际上是
\(\frac{\sum(x+y)}{2}\) ,这里要先处理出方程等于 \(gcd(a,b)\) 的两特解,即为
1 \(x\)最小正整数解,\(y\) 最大负整数解
2 \(x\)最大负整数解,\(y\) 最小正整数解
这里是因为要保证代价最小,接着根据裴蜀定理,让序列里的数膜上 \(gcd(a,b)\) 判断是否有解,然后我们要不断去找\(x,y\)的最小
加和最小解,因为\(x,y\) 之间具有方程关系,所以只需要考虑 \(x\) 的操作,再进行判断就可以了,这里可以用一个小根堆去维护,
每次取出最小代价操作,这里需要注意一个点,因为操作 \(a,b\) 时有加有减,所以\(x,y\) 可能出现负数,在这里先假设对 \(x\) 的
操作更多且为正,然后根据通解公式$$x=x_0+k*\frac{b}{gcd(a,b)}$$,
\]
每次让取出的 \(x\) 减去 \(\frac{b}{gcd(a,b)}\) ,对应的 \(y\) 加上 \(\frac{a}{gcd(a,b)}\),不断更新即可,这里可以提前求一下 \(x\) 操作数的和,最多更新次数就是
\(\frac{\sum x}{b_0}\) , \((b_0=\frac{b}{gcd(a,b)})\) 因为已经保证了 \(cnt_x\) \(>\) \(cnt_y\) ,所以对于所有的 \(y\) 一定进行更新了,最后把所有操作的 \(x,y\) 加起来再
除二即为答案
solution
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=(1<<17)+10;
long long n,m,sum[maxn],a,b,X[maxn],Y[maxn];
priority_queue <pair<int,int> >q;
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int res=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-y*(a/b);
return res;
}
bool pd(int x,int y,int xx,int yy)
{
return abs(x)+abs(y)<abs(xx)+abs(yy);
}
signed main()
{
scanf("%lld%lld%lld",&n,&a,&b);
for(int i=1;i<=n;i++)
scanf("%lld",&sum[i]);
for(int i=n+1;i>=1;i--)
{
sum[i]=sum[i]-sum[i-1];//差分,要多处理一个数0,对答案无影响
}
int x=0,y=0;
int d=exgcd(a,b,x,y);
a/=d,b/=d;
for(int xx,yy,i=1;i<=n+1;i++)
{
int c=sum[i]/d;
if(sum[i]%d!=0){puts("-1");return 0;}
xx=X[i]=(x*c%b+b)%b;//x最小正解
yy=Y[i]=(c-xx*a)/b;//y最大负解
xx-=b,yy+=a;
if(pd(xx,yy,X[i],Y[i]))X[i]=xx,Y[i]=yy;
yy=(y*c%a+a)%a;//y最小正解
xx=(c-yy*b)/a;//x最小负解
if(pd(xx,yy,X[i],Y[i]))X[i]=xx,Y[i]=yy;
yy-=a,xx+=b;
if(pd(xx,yy,X[i],Y[i]))X[i]=xx,Y[i]=yy;
}
int temp=0;
for(int i=1;i<=n+1;i++) temp+=X[i];
temp/=b;
if(temp<0)temp=-temp,swap(a,b),swap(X,Y);//保证X为正
for(int i=1;i<=n+1;i++) q.push(make_pair(-(abs(X[i]-b)+abs(Y[i]+a)-abs(X[i])-abs(Y[i])),i));
while(temp--)
{
int u=q.top().second;
q.pop();
X[u]-=b,Y[u]+=a;
q.push(make_pair(-(abs(X[u]-b)+abs(Y[u]+a)-abs(X[u])-abs(Y[u])),u));
}
int ans=0;
for(int i=1;i<=n+1;i++)ans+=abs(X[i])+abs(Y[i]);
printf("%lld",ans>>1);
return 0;
}
洛谷P3543 [POI2012] WYR-Leveling Ground的更多相关文章
- 洛谷 P3539 [POI2012]ROZ-Fibonacci Representation 解题报告
P3539 [POI2012]ROZ-Fibonacci Representation 题意:给一个数,问最少可以用几个斐波那契数加加减减凑出来 多组数据10 数据范围1e17 第一次瞬间yy出做法, ...
- 洛谷P3533 [POI2012]RAN-Rendezvous
P3533 [POI2012]RAN-Rendezvous 题目描述 Byteasar is a ranger who works in the Arrow Cave - a famous rende ...
- BZOJ2801/洛谷P3544 [POI2012]BEZ-Minimalist Security(题目性质发掘+图的遍历+解不等式组)
题面戳这 化下题面给的式子: \(z_u+z_v=p_u+p_v-b_{u,v}\) 发现\(p_u+p_v-b_{u,v}\)是确定的,所以只要确定了一个点\(i\)的权值\(x_i\),和它在同一 ...
- 洛谷P3538 [POI2012]OKR-A Horrible Poem [字符串hash]
题目传送门 A Horrible Poem 题目描述 Bytie boy has to learn a fragment of a certain poem by heart. The poem, f ...
- 洛谷P3539 [POI2012] ROZ-Fibonacci Representation
题目传送门 转载自:five20,转载请注明出处 本来看到这题,蒟蒻是真心没有把握的,还是five20大佬巨orz 首先由于斐波拉契数的前两项是1,1 ,所以易得对于任何整数必能写成多个斐波拉契数加减 ...
- 洛谷P3537 [POI2012]SZA-Cloakroom(背包)
传送门 蠢了……还以为背包只能用来维护方案数呢……没想到背包这么神奇…… 我们用$dp[i]$表示当$c$的和为$i$时,所有的方案中使得最小的$b$最大时最小的$b$是多少 然后把所有的点按照$a$ ...
- 洛谷P3531 [POI2012]LIT-Letters
题目描述 Little Johnny has a very long surname. Yet he is not the only such person in his milieu. As it ...
- 洛谷P3534 [POI2012] STU
题目 二分好题 首先用二分找最小的绝对值差,对于每个a[i]都两个方向扫一遍,先都改成差满足的形式,然后再找a[k]等于0的情况,发现如果a[k]要变成0,则从他到左右两个方向上必会有两个连续的区间也 ...
- 【洛谷3546_BZOJ2803】[POI2012]PRE-Prefixuffix(String Hash)
Problem: 洛谷3546 Analysis: I gave up and saw other's solution when I had nearly thought of the method ...
- [洛谷3457][POI2007]POW-The Flood
洛谷题目链接:[POI2007]POW-The Flood 题意翻译 Description 你手头有一张该市的地图.这张地图是边长为 m∗n 的矩形,被划分为m∗n个1∗1的小正方形.对于每个小正方 ...
随机推荐
- #交互,鸽笼原理#CF1776C Library game
题目 有一个长度为 \(m\) 的书架,以及 \(n\) 个长度 \(a_1,a_2,\dots,a_n\) Alessia 和 Bernardo 从书架上取书.每次由 Alessia 选择一个之前没 ...
- #排列组合,dp#AT2000 [AGC002F] Leftmost Ball
洛谷题目传送门 ATCODER传送门 分析 设\(dp[i][j]\)表示放完\(i\)个白球和\(j\)种有颜色的球的情况 首先\(dp[i][j]\)显然可以从\(dp[i-1][j]\)转移, ...
- 实例讲解昇腾 CANN YOLOV8 和 YOLOV9 适配
本文分享自华为云社区<昇腾 CANN YOLOV8 和 YOLOV9 适配>,作者:jackwangcumt. 1 概述 华为昇腾 CANN YOLOV8 推理示例 C++样例 , 是基于 ...
- Unity-PC 端调用SpVoice语音 (文字转语音)
第一步引用文件 在VS当中 点击项目->添加引用-> 搜索Microsoft Speech Objecet Library 然后选中前面的白色方块点击确定就行了 插入之后 你的引用库中会多 ...
- CentOS9 \ Centos8安装MySQL 8步骤
centos8 rpm 安装mysql8.0.28_太阳神LoveU的博客-CSDN博客 This upper link is still working for mysql 8 on the Cen ...
- 在centOS上配置web服务器
centos,web服务,apache,ftp服务器,mysql,makefile (1). 检查系统是否正常 # more /var/log/messages //检查有无系统内核级错误信息 # d ...
- leetcode:655. 输出二叉树
655. 输出二叉树 在一个 m*n 的二维字符串数组中输出二叉树,并遵守以下规则: 1> 行数 m 应当等于给定二叉树的高度. 2> 列数 n 应当总是奇数. 3> 根节点的值(以 ...
- (节流)js防止重复频繁点击或者点击过快方法
1.方法一:用定时器定时,没跑完定时器,点击按钮无效 <script> var isClick = true; $("button").on("click&q ...
- em/px/rem/vh/vw的区别
一.介绍 传统的项目开发中,我们只会用到px.%.em这几个单位,它可以适用于大部分的项目开发,且拥有比较良好的兼容性 从CSS3开始,浏览器对计量单位的支持又提升到了另外一个境界,新增了rem.vh ...
- 剑指offer56(Java)-数组中出现的次数Ⅰ(中等)
题目: 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 示例 1: 输入:nums = [4,1, ...