裴蜀定理巧用最短路

定义

\(x,y\) 的不定方程 \(ax + by = c\) 有整数解的充要条件是 \(\gcd(a, b)\mid c\) 。

即为如果\(a\)与\(b\)互质,那么一定存在两个整数\(x\)与\(y\),使得\(ax+by=1\)。

详见Wikiwand-斐蜀定理

例题

Codeforces Round #290 (Div. 2) D. Fox And Jumping

翻译

给出\(n\)张卡片,分别有\(l_i\)和\(c_i\)。在一条无限长的纸带上,你可以选择花\(c_i\)的钱来购买卡片\(i\),从此以后可以向左或向右跳\(l_i\)个单位。问你至少花多少元钱才能够跳到纸带上全部位置。若不行,输出\(-1\)。

思路

  • 正解:斐蜀定理+动态规划
  • 最优解:斐蜀定理+\(Dijkstra\)

分析该问题,先考虑两个数的情况,发现想要跳到每一个格子上,必须使得这些数通过数次相加或相加得出的绝对值为\(1\),进而想到了斐蜀定理。

如果\(a\)与\(b\)互质,那么一定存在两个整数\(x\)与\(y\),使得\(ax+by=1\)。

由此得出了若选择的卡牌的数通过数次相加或相减得出的绝对值为\(1\),那么这些数一定互质,此时可以考虑动态规划求解。

不过可以转移思想,因为这些数互质,即为\(0\)号节点开始,每走一步求\(Gcd\)(节点号,下一个节点),同时记录代价,就成为了从\(0\)通过不断\(Gcd\)最后变为\(1\)的最小代价。

由于:互质即为最大公因数为\(1\),\(Gcd(0,x)=x\)这两个定理,可以证明该算法的正确。选择优先队列优化\(Dijkstra\)求解。

不过还有个问题,即为需要记录是否已经买过一个卡片,开数组标记由于数据范围达到\(10^9\)会超出内存限制,可以想到使用unordered_map(比普通的map更快地访问各个元素,迭代效率较低)来标记。

另外,__gcd是\(OI\)禁用的函数,仅供平时练习所用。

Code

#include<bits/stdc++.h>
using namespace std;
int n,t[300],k[300];
unordered_map<int,int>mp;
priority_queue<pair<int,int>>q;
void add(int g,int k)
{
    if(mp.find(g)==mp.end()||mp[g]>k)
    {
        mp[g]=k;
        q.push({-k,g});
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&t[i]);
    for(int i=0;i<n;i++) scanf("%d",&k[i]);
    add(0,1);
    while(!q.empty())
    {
        int u=q.top().second;
        int w=-q.top().first;
        q.pop();
        if(mp[u]!=w)  continue;
        if(u==1) return printf("%d\n",w-1),0;
        for(int i=0;i<n;i++) add(__gcd(u,t[i]),k[i]+w);
    }
    puts("-1");
    return 0;
}

原文地址:https://www.cnblogs.com/lyfoi/p/9485063.html

时间: 2024-10-14 01:48:32

裴蜀定理巧用最短路的相关文章

BZOJ 2299 向量(裴蜀定理)

题意:给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y). 实际上前四个向量能拼出(ma,nb)(m%2=n%2).后四个向量拼出(xb,ya)(x%2=y%2). 这样可以枚举这四个未知数在模二意义下的解.这两个向量相加为(ma+xb,nb+ya). 对于ma+xb=X.根据系数的奇偶性,如果有系数为奇数,可使得等式两边都减去一个数使得系数都为偶

贝祖定理(裴蜀定理)

在数论中,裴蜀定理是一个关于最大公约数(或最大公约式)的定理:若a,b是整数,且(a,b)=d,那么对于任意的整数x,y,ax+by=m中的m一定是d的倍数. 特别地,一定存在整数x,y,使ax+by=d成立,且不止一组,例如(12,42)=6,则方程12x + 42y = 6有解,事实上有(-3)×12 + 1×42 = 6及4×12 + (-1)×42 = 6. 而ax+by=1是a,b两数互质的充要条件,同样地,x,y不止一组. 参考:http://www.cnblogs.com/tekk

【BZOJ-2299】向量 裴蜀定理 + 最大公约数

2299: [HAOI2011]向量 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1118  Solved: 488[Submit][Status][Discuss] Description 给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y). 说明:这里的拼就是使得你选出的向量之和为(x,y)

【BZOJ-1441】Min 裴蜀定理 + 最大公约数

1441: Min Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 471  Solved: 314[Submit][Status][Discuss] Description 给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1*X1+...An*Xn>0,且S的值最小 Input 第一行给出数字N,代表有N个数下面一行给出N个数 Output S的最小值 Sample Input 24059 -1782 Sample Outpu

bzoj 2299 [HAOI2011]向量 裴蜀定理

bzoj 2299 [HAOI2011]向量 裴蜀定理 题意: 给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y). 限制: -2*1e9 <= a,b,x,y <= 2*1e9 思路: 题目的操作可以化为: 1. x +- 2a; 2. y +- 2a; 3. x +- 2b; 4. y +- 2b; 5. x + a && y

扩展欧几里得算法、裴蜀定理与乘法逆元

扩展欧几里得算法 扩展欧几里得算法(扩O)能在求gcd(a,b)的同时求出丢番图方程ax+by=gcd(a, b)的解. 然而怎么求呢?我们观察gcd(a, b)=gcd(b, a%b),所以设如下两个方程: ax+by = gcd(a,b) = d: bx'+(a%b)y' = gcd(b,a%b): 明显gcd(a,b) = gcd(b,a%b),也就是ax+by = bx'+(a%b)y'. 为了求得x与y,我们需要保证a,b不变,所以:ax+by = bx'+(a%b)y' = bx'+

BZOJ 2257: [Jsoi2009]瓶子和燃料【数论:裴蜀定理】

2257: [Jsoi2009]瓶子和燃料 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1326  Solved: 815[Submit][Status][Discuss] Description jyy就一直想着尽快回地球,可惜他飞船的燃料不够了. 有一天他又去向火星人要燃料,这次火星人答应了,要jyy用飞船上的瓶子来换.jyy 的飞船上共有 N个瓶子(1<=N<=1000) ,经过协商,火星人只要其中的K 个 . jyy 将 K个瓶子交给

[BZOJ1441&amp;BZOJ2257&amp;BZOJ2299]裴蜀定理

裴蜀定理 对于整系数方程ax+by=m,设d =(a,b) 方程有整数解当且仅当d|m 这个定理实际上在之前学习拓展欧几里得解不定方程的时候就已经运用到 拓展到多元的方程一样适用 BZOJ1441 给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1*X1+...An*Xn>0,且S的值最小 该方程有解当且仅当gcd(A1...AN)|s 要求s的值最小,那么答案就是gcd(A1..AN) BZOJ2257 jyy就一直想着尽快回地球,可惜他飞船的燃料不够了.有一天他又去向

【BZOJ】1441: Min(裴蜀定理)

http://www.lydsy.com/JudgeOnline/problem.php?id=1441 这东西竟然还有个名词叫裴蜀定理................ 裸题不说....<初等数论>上边写得很清楚:如果对于任意d|ai,有d|sum{aixi} 所以求出d就行了...显然gcd.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #in