题目描述

给定 \(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)}$$,

\[y=y_0+k*\frac{a}{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的更多相关文章

  1. 洛谷 P3539 [POI2012]ROZ-Fibonacci Representation 解题报告

    P3539 [POI2012]ROZ-Fibonacci Representation 题意:给一个数,问最少可以用几个斐波那契数加加减减凑出来 多组数据10 数据范围1e17 第一次瞬间yy出做法, ...

  2. 洛谷P3533 [POI2012]RAN-Rendezvous

    P3533 [POI2012]RAN-Rendezvous 题目描述 Byteasar is a ranger who works in the Arrow Cave - a famous rende ...

  3. 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\),和它在同一 ...

  4. 洛谷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 ...

  5. 洛谷P3539 [POI2012] ROZ-Fibonacci Representation

    题目传送门 转载自:five20,转载请注明出处 本来看到这题,蒟蒻是真心没有把握的,还是five20大佬巨orz 首先由于斐波拉契数的前两项是1,1 ,所以易得对于任何整数必能写成多个斐波拉契数加减 ...

  6. 洛谷P3537 [POI2012]SZA-Cloakroom(背包)

    传送门 蠢了……还以为背包只能用来维护方案数呢……没想到背包这么神奇…… 我们用$dp[i]$表示当$c$的和为$i$时,所有的方案中使得最小的$b$最大时最小的$b$是多少 然后把所有的点按照$a$ ...

  7. 洛谷P3531 [POI2012]LIT-Letters

    题目描述 Little Johnny has a very long surname. Yet he is not the only such person in his milieu. As it ...

  8. 洛谷P3534 [POI2012] STU

    题目 二分好题 首先用二分找最小的绝对值差,对于每个a[i]都两个方向扫一遍,先都改成差满足的形式,然后再找a[k]等于0的情况,发现如果a[k]要变成0,则从他到左右两个方向上必会有两个连续的区间也 ...

  9. 【洛谷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 ...

  10. [洛谷3457][POI2007]POW-The Flood

    洛谷题目链接:[POI2007]POW-The Flood 题意翻译 Description 你手头有一张该市的地图.这张地图是边长为 m∗n 的矩形,被划分为m∗n个1∗1的小正方形.对于每个小正方 ...

随机推荐

  1. 中文GPTS详尽教程,字节扣子Coze插件使用全输出

    今天,斜杠君和大家分享如何在字节扣子Coze中创建插件,并在创建后如何使用这个插件. 一.新建插件 首先,进入到插件页面,创建一个插件. https://www.coze.cn/home 点击左侧的个 ...

  2. C# 方法详解:定义、调用、参数、默认值、返回值、命名参数、方法重载全解析

    C# Methods 方法是一段代码,只有在调用时才会运行. 您可以将数据(称为参数)传递给方法. 方法用于执行某些操作,也被称为函数. 为什么使用方法?为了重用代码:定义一次代码,然后多次使用. 创 ...

  3. linux 性能自我学习 ———— 软中断 [五]

    前言 linux 性能的自我学习. 正文 什么是软中断呢? 举一个网络的例子. linux 将中断处理过程分为两个阶段: 上半部用来快速处理中断,他在中断禁止模式下运行,注意是处理跟硬件紧密相关或时间 ...

  4. 整理ionic 系列——页面生命周期

    前言 这是整理ionic的开篇,ionic 就不多介绍了,开发混合app的. 正文 Event Desc ionViewDidLoad 当页面加载的时候触发,仅在页面创建的时候触发一次,如果被缓存了, ...

  5. Java进行excel的导入导出操作

    excel表格的导出导入在业务中经常会遇到,下面介绍hutool和easyExcel两种操作excel的工具 测试的实体类 通过mybatis-plus生成的,用于导出数据的实体类 @Getter @ ...

  6. Flink Standalone集群部署

    Flink Standalone模式部署集群是最简单的一种部署方式,不依赖于其他的组件,另外还支持YARN/Mesos/Docker等模式下的部署,这里使用的flink版本为最新的稳定版1.9.1版本 ...

  7. Causal Inference理论学习篇-Tree Based-Causal Forest

    广义随机森林 了解causal forest之前,需要先了解其forest实现的载体:GENERALIZED RANDOM FORESTS[6](GRF) 其是随机森林的一种推广, 经典的随机森林只能 ...

  8. NL2SQL技术方案系列(1):NL2API、NL2SQL技术路径选择;LLM选型与Prompt工程技巧,揭秘项目落地优化之道

    NL2SQL技术方案系列(1):NL2API.NL2SQL技术路径选择:LLM选型与Prompt工程技巧,揭秘项目落地优化之道 NL2SQL基础系列(1):业界顶尖排行榜.权威测评数据集及LLM大模型 ...

  9. 顺通鞋服进销存OA管理系统

    鞋服进销存OA管理系统通过十几年的积淀与创新,顺通与众多鞋服企业一起共创,形成了涵盖协同办公.移动办公.知识管理.数据运营.多维门户等领域,以鞋服新品研发管理.生产排班管理.门店一体化管理.市场费用管 ...

  10. 力扣693(java)-交替位二进制数(简单)

    题目: 给定一个正整数,检查它的二进制表示是否总是 0.1 交替出现:换句话说,就是二进制表示中相邻两位的数字永不相同. 示例 1: 输入:n = 5输出:true解释:5 的二进制表示是:101示例 ...