1. 程式人生 > >20180418模擬賽T2——Gym

20180418模擬賽T2——Gym

clas fin div 不能 mod span input typedef 都沒有

Gym

(Gym.cpp/c/pas)

題目描述 Description

木吉終於到達了 VAN 様的老巢 gym,然而他已經是孤身一人。他決定和 VAN 様來一場對決。他決定和 VAN 様玩♂跑♂步。已知跑道長$ l \(米,而木吉一步能跑且只能跑\) n \(米,VAN様一步能跑且只能跑\) m \(米。現在規定選手不能跑出\) k \(米。而誰最後跑得遠誰就贏了。出於公平起見,\)k$是一個$1 \(到\) l $之間完全隨機的正整數。現在木吉想要知道,自己和 VAN 様打成平局的概率是多少。

輸入描述 (gym.in) Input Description

第一行為三個整數,依次為\(l,n,m\)

;

輸出描述 (gym.out) Output Description

一個約分後的真分數,格式為a/b,為木吉和 VAN 様打成平局的概率

樣例輸入 Sample Input

10 3 2

樣例輸出 Sample Output

3/10

樣例解釋 Sample Interpretation

當$ k $為$1,6,7 $時,木吉會和 VAN 様打成平局

數據範圍 Data Size

對於 30%的數據,\(n,m,l\le 10^6\)

對於 100%的數據,\(n,m,l\le 5\times {10}^{18}\)

題解

首先確定這是一道數論題,於是就往此方向想。

顯然,木吉和 VAN 様打成平局的充要條件是:\(k\mod n=k\mod m\)

不難發現,當\(n=m\)時,\(k\)顯然成立。而上式會報錯,於是需要特判一下:

if(n==m)
{
    fout<<"1/1";
    return 0;
}

然後繼續開始愉快的推導……

將上式中\(k\)轉化為帶余除式,有\(k-t_1 n=k-t_2 m\)\(t_1 n=t_2 m\)

設滿足木吉和 VAN打成平局的\(k\)的總數為\(ans\)

不難發現,當\(k=\infty\)時,木吉和 VAN首次相遇是在\([a,b]\)處。於是,當\(k<[a,b]\)時,\(ans=\min(m,n)\)(兩個人都沒有跨出一步)。

按照這個思路,我們發現兩人在\([a,b]\)

處與在起點處是等價的。於是我們就不難推出正解。

毒瘤的是\([a,b]\)unsigned long long竟存不下……於是在必要情況下必須用long double

代碼

#include <fstream>
#include <algorithm>

using namespace std;

typedef long long LL;

LL l,n,m;

int main()
{
    ifstream fin("gym.in");
    ofstream fout("gym.out");
    fin>>l>>n>>m;
    if(n==m)
    {
        fout<<"1/1";
        fin.close();
        fout.close();
        return 0;
    }
    LL t=min(n,m);
    LL ans=t-1;
    if(ans>l)
    {
        fout<<"1/1";
        fin.close();
        fout.close(); 
        return 0;
    }
    LL g=__gcd(m,n);
    LL lcm=m/g*n;
    if((long double)m/g*n<=(long double)l)
        ans+=l/lcm*t;
    LL tmp=__gcd(ans,l);
    fout<<ans/tmp<<‘/‘<<l/tmp;
    fin.close();
    fout.close();
    return 0;
}

20180418模擬賽T2——Gym