裴蜀定理


裴蜀定理:

定义:

\(a,b\) 不全为零,则存在 \(x,y\) ,使得 \(ax+by=gcd(a,b)\)

证明:

记住就行了,证明太长了不想写了.....

例题:

CF510D Fox And Jumping

题意:

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

分析:

先考虑两个数情况:想要跳到每一个格子上,必须使得这些数通过数次相加/减得出的绝对值为 \(1\) ,进而想到了裴蜀定理。

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

若选择的卡牌通过数次相加或相减得出的绝对值为 \(1\) ,那么这些数一定互质.

因此问题转化成:选择若干个数使得 \(gcd\)\(1\) 的最小代价。

考虑类似于背包的动态规划:设 \(gcd=x\) 的最小代价为 \(f_x\), 则式子为:

\[x=2,3,4,....,l_i,f_{gcd(x,l_i)}=min(f_{gcd(x,l_i)},f_x+c_i) \]

但是时间复杂度不行。

我们考虑消去无用状态:用 \(map\) 记录,每次访问过的 \(x\) 进行转移,差不多能过。

然后直接写就行了。

代码:

#include<bits/stdc++.h>
using namespace std;

map<int,int> mp;
int a[1005],b[1005];
int n;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    for(int i=1;i<=n;i++){
        for(pair<int,int> x:mp){
            int num=__gcd(a[i],x.first);
            int val=x.second+b[i];
            if(mp[num]==0) mp[num]=val;
            else mp[num]=min(mp[num],val);
        }
        if(mp[a[i]]==0) mp[a[i]]=b[i];
        else mp[a[i]]=min(mp[a[i]],b[i]);
    }
    if(mp[1]==0) puts("-1");
    else printf("%d\n",mp[1]);
    system("pause");
    return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM