首页 > 其他分享 >数列

数列

时间:2024-11-29 20:34:57浏览次数:5  
标签:return 数列 gcd1 int exgcd gcd

题目描述:

给定一个长度为 \(n\) 的数列,每次操作你可以将数列中的一个数字加上一个整数 \(t\),其中 \(t\) 必须满足 \(|t| = a\) 或 \(|t| = b\)。
你需要将所有数全部变为 \(0\),无解输出 \(-1\),否则输出最小操作数。

解题思路:

一眼 exgcd,但是场上不会,输。

推一下 exgcd 吧,首先要用到裴蜀定理,如果 \(ax+by=c\) 有解,则 \(c|gcd(a,b)\),那么我们就可以轻松判断有无解了。

思考如何搞出一组解,因为 \(gcd(a,b)=gcd(b,a\%b)\), 所以要求 \(ax+by=gcd(a,b)\) 的一组解,可以先求 \(bx+(a\%b)y=gcd(b,a \%b)\) 的一组解,然后往回带。

一直做到 \(b=0\),那么一组可行的解就是 \(x=1,y=0\)。

注意到 \(a \%b=a-\lfloor a/b\rfloor *b\),那么我们可以化式子: \(bx+(a-\lfloor a/b\rfloor *b)y \rightarrow ay+b(x-\lfloor a/b\rfloor y)\) 则新的 \(x,y\) 也随之而出了。

但是这样我们只是解出了一组解,怎么使得 \(x,y\) 的绝对值之和最小呢?

需要一个结论那就是 \(x\) 的最优解一定是取可能的最小正值或最大的非负值,比较即可,注意 \(0\) 的情况。

代码实现:

#include<bits/stdc++.h>
#define int long long
using namespace std;
void exgcd(int a, int b, int &x, int &y){
    if(b == 0){
        x = 1, y = 0;
        return;
    }
    exgcd(b, a % b, x, y);
    int t = x;
    x = y, y = t - (a / b) * y;
    return;
}
int gcd(int a, int b){
    return b == 0 ? a : gcd(b, a % b);
}
int n, A, B, ans;
signed main(){
    freopen("array.in", "r", stdin);
    freopen("array.out", "w", stdout);
    cin >> n >> A >> B;
    int gcd1 = gcd(A, B);
    A /= gcd1, B /= gcd1;
    if(A > B) swap(A, B);
    for(int i = 1; i <= n; i++){
        int c;
        cin >> c;
        if(c % gcd1 != 0) return cout << "-1" << endl, 0;
        c /= gcd1;
        int x = 0, y = 1;
        exgcd(A, B, x, y);
        x = c * x, y = c * y;
        int k = x / B, res = 0x3f3f3f3f3f3f3f3f;
        for(int j = -2; j <= 2; j++)
            res = min(res, abs(x - (k + j) * B) + abs(y + (k + j) * A));
        ans += res;
    }
    cout << ans << endl;
    return 0;
}

标签:return,数列,gcd1,int,exgcd,gcd
From: https://www.cnblogs.com/huangweiliang/p/18577429

相关文章

  • 洛谷题单指南-线段树-P1438 无聊的数列
    原题链接:https://www.luogu.com.cn/problem/P1438题意解读:给定序列a[n],支持两种操作:1.给区间[l,r]每个数增加一个对应位置等差数列的元素,首项k,公差d;2.查询第x个元素值解题思路:直接用线段树求解。要实现区间修改,需要引入懒标记,而这里修改的值是要增加一个等差数列的某一项,需要保......
  • 【分块】LibreOJ 6281 数列分块入门5
    前言对一个int类型的非负整数进行开方下取整,最多只会开方四次大小就不会再发生变化。一个大于\(0\)的正整数开方下取整最后的结果比如是\(1\),而\(1\)开方的结果仍然会是\(1\);\(0\)开方的结果仍是\(0\)。验证int类型整数最多可以开方的次数的demo#include<bits/stdc+......
  • 【分块】LibreOJ 6280 数列分块入门4
    题目https://loj.ac/p/6280题解将\(n\)个元素的数组\(a\)按块长\(\sqrt{n}\)进行分块处理。为每个块设置两个懒添加标记\(add[i],sum[i]\),分别代表这个区间每个元素共同添加的数值大小,区间和(不包括懒添加的值)。对于区间加操作,将添加值存储在符合整块都进行加法操作的......
  • C语言实例之9斐波那契数列实现
    1.斐波那契数列简介斐波那契数列(Fibonaccisequence),又称黄金分割数列,因数学家莱昂纳多・斐波那契(LeonardoFibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。它的特点是从第三项开始,每一项都等于前两项之和,数列的前两项通常定义为0和1(也有从1和1开始的定义......
  • 请使用原生的js实现斐波那契数列
    functionfibonacci(n){if(n<=0){return0;}elseif(n===1){return1;}else{leta=0;letb=1;lettemp;for(leti=2;i<=n;i++){temp=a+b;a=b;b=temp;}returnb......
  • 【分块】LibreOJ 6278 数列分块入门2
    题目https://loj.ac/p/6278题解将\(n\)个元素的数组\(a\)按块长\(\sqrt{n}\)进行分块处理。为每个块设置一个懒添加标记\(add[i]\),代表这个区间每个元素共同添加的数值大小。对于任意一个无序数组,想要维护出该数组内小于某个值的元素个数,时间复杂度都将来到\(O(n)\);对......
  • 【分块】LibreOJ 6279 数列分块入门3
    题目https://loj.ac/p/6279题解将\(n\)个元素的数组\(a\)按块长\(\sqrt{n}\)进行分块处理。为每个块设置一个懒添加标记\(add[i]\),代表这个区间每个元素共同添加的数值大小。对于任意一个无序数组,想要维护出该数组内某个值的前驱(即小于某个值的最大元素),时间复杂度都将......
  • PG优化-业务场景需求实现-大表低基数列group by优化
    PG优化-业务场景需求实现-大表低基数列groupby优化原创 akengan DB印象  2021年11月07日22:18阅读使人充实,讨论使人敏捷,写作使人精确。 前言 今天抽空聊一个和成本优化相关的话题。 说到成本优化,大家觉得优化多少算不错呢? 10%?20%? 成本优化的空间到底有多......
  • Java编程实例之---Java 中的斐波那契数列
    用Java实现斐波那契数列是一项经典的编程练习,可以很好地介绍递归、动态规划和数学概念。在本节中,我们将探讨用Java实现斐波那契数列的各种方法,讨论它们的优缺点,并深入研究底层数学。斐波那契数列斐波那契数列是一系列数字,其中每个数字都是前两个数字的总和。换句话说,在斐......
  • 递推数列的极限(上)------单调有界部分
    不管怎么样,求极限之前都要先证明极限存在,即数列收敛。证明数列收敛两种方法:一种是单调有界准则,一种是夹逼准则。一.单调有界准则例1上面这道题的心路历程:先在草稿纸用上帝视角求出‘极限’,虽然是猜的,但是一定是对的。然后根据这个极限,以及题目给的条件,比如这道题给......