题目描述

给定 \(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. 使用OHOS SDK构建freetype

    参照OHOS IDE和SDK的安装方法配置好开发环境. 从github下载源码. 执行如下命令: git clone https://github.com/freetype/freetype.git ...

  2. Windows Terminal的资料

    Windows Terminal是微软Windows平台难得好用的工具. 由于工作内容的原因,需要打开多个CMD窗口.多个git bash窗口,并且在多个窗口间切换,因此命令行窗口支持多TAB的特性, ...

  3. 王莉:将开发文档英文化和本地化,我们努力让OpenHarmony走向全球

    编者按:在 OpenHarmony 生态发展过程中,涌现了大批优秀的代码贡献者,本专题旨在表彰贡献.分享经验,文中内容来自嘉宾访谈,不代表 OpenHarmony 工作委员会观点. 王莉 华为技术有限 ...

  4. Blazor OIDC 单点登录授权实例7 - Blazor hybird app 端授权

    目录: OpenID 与 OAuth2 基础知识 Blazor wasm Google 登录 Blazor wasm Gitee 码云登录 Blazor OIDC 单点登录授权实例1-建立和配置IDS ...

  5. 通过path在windows下临时修改python和pip路径 以便于配置环境只对当前命令行窗口生效

    配置前 在cmd命令行下输入新env的路径 path=D:\Miniconda2\envs\openmmlab\openmmlab;D:\Miniconda2\envs\openmmlab\openm ...

  6. Docker之离线安装和在线安装

    一.离线安装 1.软件包下载 https://download.docker.com/linux/static/stable/x86_64/ 2.安装docker tar xvf /opt/docke ...

  7. 10个常用的JS工具库,80%的项目都在用

    高手区别于普通人的重要一点是,他们善于利用工具,把更多的时间留给了规划和思考.写代码也是同样的道理,工具用好了,你就有更多的时间来规划架构和攻克难点.今天就给大家分享一下当前最流行的 js 工具库,如 ...

  8. MAC上Cisco AnyConnect删除不干净,造成无法重新安装的解决办法

    1.问题 由于直接删除而不是正常卸载,导致文件残留,无法正常安装,并且软件不可用 2.解决 2.1 终端运行命令 pkgutil --pkgs|grep com.cisco 查看cisco残留的文件 ...

  9. 【.net】Error while trying to retrieve text for error ORA-06413

    [.net]Error while trying to retrieve text for error ORA-06413 系统需要,有一个外挂系统使用的是.net,出了问题,所以部署环境查询代码 但 ...

  10. 阿里云 ACK One 多集群管理全面升级:多集群服务、多集群监控、两地三中心应用容灾

    简介: 本文介绍了 ACK One 近期发布的 3 个主要特性,覆盖了多集群管理的 3 个主要场景,跨集群服务发现与访问.多集群全局监控.应用容灾.除多集群管理外,ACK One 更是支持连接并管理任 ...