裴蜀定理


裴蜀定理:

定義:

\(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