1. 程式人生 > >C. Lucky Days 題解(cf)(裴蜀定理思想)

C. Lucky Days 題解(cf)(裴蜀定理思想)

題目連結:bang

題意:給出兩組 l, r,t 表示 在區間 [ l+k*t , r+k*t ] (k屬於非負整數)內是幸運的,問兩組最多連續幸運天數是多少天?

先給出裴蜀定理的概念,參考百度百科。

對任意兩個整數a、b設d是它們的最大公約數。那麼關於未知數x和y的線性丟番圖方程(稱為裴蜀等式):

ax + by = m

有整數解(x,y)當且僅當m是d的倍數。裴蜀等式有解時必然有無窮多個解。

我們可以用拓展歐幾里得求整數解(x,y)。

 

題解:要想使兩組連續幸運天數儘可能的多,那就要想辦法兩組幸運區間要儘量對齊,那麼我們就以右邊界儘量對齊為基準,

給出兩個區間 [la,ra] [lb,rb] (設ra<rb),gcd=gcd(ta,tb),我們要讓ra靠近rb,只需將ra加上 m*gcd (m=(rb-ra)/gcd),相應的la也是加上同樣的。為什麼可以這樣直接加呢?按道理不是應該加上 ta*k的嗎?不急,我先給個樣例:

4 6 12 和 11 13 18 ,按上面的方法,gcd=6,m=1,那麼第一個區間靠近第二個區間就差6了,第一個區間加完(13-6)/6*6=6後就變成 [10,12] ,那麼此時連續天數是2天,咦?

怎麼能加6呢?應該是加12*k的啊?我來解釋一下,第一個區間加完後

[10,12]與第二個區間[11,13]的狀態一定會存在,狀態如下圖所示:

  就是說會在之後的某個區間,這裡其實就是 [64,66](12*5)(加的值) 和 [65,67] (18*3)這兩個區間,而這裡12*5-18*3=6的,剛好是我們把第一個區間[4,6]變成[10,12]的m*gcd=6的值,那麼這說明上面的方法是正確的。其實也就是看看 12*x+18*y=6 有沒有整數解,因為 gcd(12,18)|6,根據裴蜀定理一定有整數解。所以以後我們只需加上m*gcd就行了,因為ta*x+tb*y=m*gcd,而gcd(ta,tb)|m*gcd,故一定有整數解。

 

程式碼參考連結如下:https://blog.csdn.net/SwustLpf/article/details/84064459

#include<cstring>
#include<algorithm>
#include<cstdio>

using namespace std;

int gcd(int a,int b)
{
    if(!b) return a;
    else return gcd(b,a%b);
}

int solve(int a,int b,int x,int y){ ///計算兩個區間公共的數

    return min(b,y)-max(a,x)+1;
}

int main()
{
    int la,ra,ta,lb,rb,tb;

    while(~scanf("%d%d%d%d%d%d",&la,&ra,&ta,&lb,&rb,&tb))
    {

        la++,ra++,lb++,rb++;

        int item=gcd(ta,tb); 

        if(ta==tb){ ///兩個區間已經最靠近了,故直接算就行了
            printf("%d\n",solve(la,ra,lb,rb));
            continue;
        }
        int m,ans;
        if(ra<=rb){
             m=(rb-ra)/item;
            la+=m*item;
            ra+=m*item;
             ans=0; ///注意此處初始化為0,
             
///因為我們加的不一定剛好對齊,只需在不超過(儘量靠近)另一個區間和超過(儘量靠近)另一個區間之間選一個最大值就好了
            
            ans=max(ans,solve(la,ra,lb,rb)); 

            ans=max(ans,solve(la+item,ra+item,lb,rb));
        }
        else{
             m=(ra-rb)/item;
            lb+=m*item;
            rb+=m*item;
             ans=0;

            ans=max(ans,solve(la,ra,lb,rb));

            ans=max(ans,solve(la,ra,lb+item,rb+item));
        }

        printf("%d\n",ans);
    }
}