數學測試3(test20170311pm)

【INDEX1】(Indexone.pas/c/cpp Time:1s Memory:256M)

【問題描述】

INDEX 是誰?兄弟,這個問題你如果不知道我就只能懷疑你是從火星來的了。 但是,如果你真的不知道他是誰,那麼,你可能和他擁有同一個故鄉。 其實當年 INDEX 在火星上有 N 個基友和 M 個妹子,生活真是非常逍遙。他每天都把 基友和妹子排成一隊,使得他能夠站在最前面,領着他的基友後宮團遊街(囧)。 但是,他的妹子們的嫉妒心是很強的,如果兩個妹子站在一起,肯定會爲 INDEX 吵得 不可開交。同時,INDEX 也是有老婆的人,他身後,也就是隊伍的第一個人必須是他的基 友後宮團的團長——他老婆(也就是說,M 個妹子中有一個是他的老婆,爲了使題目容易 理解,也就是第一個人已經確定是 M 個妹子中的一個了)。而且,他希望由一個基友來殿後。 現在 INDEX 想知道,他能夠排成多少種不同的隊伍,使得這個隊伍滿足他的要求?

【輸入】

輸入文件名爲 Indexone.in。 輸入一行包含兩個整數 N 和 M。

【輸出】

輸出文件名爲 Indexone.out。 輸出一行,表示合法的隊伍總數對 1000000007 的模值,如果不存在何方方案則輸出 0

【輸入輸出樣例】

Indexone.in

1 1

Indexone.out

1

【數據範圍】

對於 30%的數據,保證有1≤N,M≤1000。

對於另外 30%的數據,保證有1≤M≤10。

對於 100%的數據,保證有1≤N,M≤1000000。

【題解】

這個題其實和那個什麼01序列差不多,答案:

ans=n!×pm1n1(modp)

【代碼】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long long LL;
const int MOD = 1000000007;
const int size = 1000010;
LL a[size],b[size];
LL n,m,ans=1;

LL ksm(LL,LL,LL);

int main() {
    freopen("indexone.in","r",stdin);
    freopen("indexone.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    if(m>n)
        return puts("0"),0;
    a[0]=1;
    for(LL i=1;i<=n;i++)
        a[i]=a[i-1]*i%MOD;
    b[n]=ksm(a[n],MOD-2,MOD);
    b[0]=1;
    for(LL i=n-1;i>=1;i--)
        b[i]=b[i+1]*(i+1)%MOD;
    ans=a[n]*a[n-1]%MOD*b[n-m]%MOD;
    printf("%lld\n",ans);
    return 0;
}

LL ksm(LL x,LL y,LL Mod) {
    x%=Mod;
    LL ret=1;
    while(y) {
        if(y&1)
            ret=ret*x%Mod;
        x=x*x%Mod;
        y>>=1;
    }
    return ret;
}

【INDEX2】(Indextwo.pas/c/cpp Time:1s Memory:256M)

【問題描述】

故事承接上文。 這事發生在博士還不那麼內涵,現哥還不那麼傻逼,姜嗲還沒開始玩 dota,巨胖才 50Kg 的時候。有一天,INDEX 的老婆再也不能忍受 INDEX 那過分龐大超過一阿伏伽德羅常數的 後宮量,那天夜裏,她將 INDEX 綁架到了飛船上,“私奔”到了月球,在《Fly me to the moon》 的歌聲中。好美啊! 這個時刻,INDEX 發現有一顆藍色的星球一直在繞着一顆紅色的星球轉動。接着,他 又發現,他的故鄉火星也一直在繞着這顆紅色的星球轉動!!!厲害爆了有木有!!!現在,他 的老婆將這顆藍色星球命名爲 A,他們的故鄉火星命名爲 B,並將他們的軌道平均分成 L 塊,形成了 L 塊扇形區域嗎,並從 0 到 L-1 逆時針標號,A 星球和 B 星球都是沿逆時針繞 紅色星球轉動。一開始的時間計算爲 0,在 0 時刻時,A 處在 Sa 塊,B 處在 Sb 塊。A 的移 動速度爲 Va 塊每 INDEX 小時,B 的移動速度爲 Vb 塊每 INDEX 小時。INDEX 向她老婆發 誓,他們會在月球上度過一段美好的二人時光,直到到某個 INDEX 小時整點的鐘聲敲響時, 若星球 A 和星球 B 所在塊的編號相同,那麼,他們啓程返回火星。 思念自己龐大後宮團的 INDEX 想問你,他們啓程返回火星的時刻。

【輸入】

輸入文件名爲 Indextwo.in。 輸入僅一行,包含五個正整數,分別爲 L,Sa,Sb,Va,Vb。

【輸出】

輸出文件名爲 Indextwo.out 輸出僅一行,表示他們啓程返回火星的時刻。若永遠都不存在那個時刻,請輸出 “Ohahahahahahaha”,不包含雙引號。

【輸入輸出樣例】

Indextwo.in

3 1 1 2 2

Indextwo.out

0

【數據範圍】

對於 30%的數據,保證有 1≤L≤100。

對於 100%的數據,保證有 1≤L≤1000000,而且 0≤Sa,Sb≤L-1,1≤Va,Vb≤L。

【題解】

我們可以發現問題可以轉化爲求Sa+VaxSb+Vbx(modl) 的最小整數解。
可以轉化爲x(VaVb)lk=SbSa
此時可以很明顯發現用擴展gcd就可以求出一個解,那麼求通解就很簡單了。而我們只要當中的最小整數解。
【代碼】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long long LL;
LL l,sa,sb,va,vb;
LL x,y;

void swap(int &a,int &b) {
    a^=b;b^=a;a^=b;
}

LL ex_gcd(LL a,LL b,LL &x,LL &y) {
    if(b==0) {
        x=1;y=0;
        return a;
    }
    LL ret=ex_gcd(b,a%b,y,x);
    y-=x*(a/b);
    return ret;
}

int main(){
    freopen("indextwo.in","r",stdin);
    freopen("indextwo.out","w",stdout);
    scanf("%lld%lld%lld%lld%lld",&l,&sa,&sb,&va,&vb);
    if(va<vb) {
        swap(va,vb);
        swap(sa,sb);
    }
    if(sa==sb)
        return puts("0"),0;
    LL Gcd=ex_gcd(va-vb,l,x,y);
    if((sb-sa)%Gcd!=0)
        return puts("Ohahahahahahaha"),0;
    LL bd=l/Gcd; 
    x*=((sb-sa)/Gcd);
    x=(x%bd+bd)%bd;
    printf("%lld\n",x);
    return 0;
}

【INDEX3】(Indexthree.pas/c/cpp Time:1s Memory:256M)

【問題描述】

故事承接上文。 INDEX 回家之後,果斷廢棄了他的後宮基友團。開始和他老婆移居到農村,在一個 N 行 M 列的土地上,在平面直角座標系中,就是橫座標從 1 到 N,縱座標從 1 到 M 的地方上 種植樹木。特別的,在原點那裏,有一個 INDEX 造的太陽。然而,這次種植的樹木名字叫 做超能樹,爲啥叫超能呢,因爲它超需要能量,所以叫做超能樹,如果這棵樹無法從 INDEX 造的太陽中獲得能量,也就是有其它樹擋住了它的陽光,它就會死去。一棵樹擋住了另一棵 樹當且僅當這兩棵樹與原點三點共線,且一棵樹距離原點更近。INDEX 已經種植了在他的 土地上的每個整點上都種植了一棵超能樹。INDEX 想知道,有多少樹可以活下來?

【輸入】

輸入文件名爲 Indexthree.in。 輸入僅一行,包含兩個正整數 N 和 M。

【輸出】

輸出文件名爲 Indexthree.out。 輸出僅一行,表示最後活下來的樹木個數。

【輸入輸出樣例】

Indexthree.in

2 2

Indexthree.out

3

【樣例解釋】

(2,2)上的樹被(1,1)上的樹擋住了,所以只有兩棵樹成活。

【數據範圍】

對於 60%的數據,保證有 1≤N,M≤1000。

另外 20%的數據,保證 N=M。

對於 100%的數據,保證有 1≤N,M≤1000000。

【題解】

易知,(x,y) 上的樹不被其它樹擋住的充要條件是gcd(x,y)=1。
因爲若gcd(x,y)=d,d>1,那麼 (x,y) 上的樹必會被(x/d,y/d) (注:不知爲何公式gg了)上的樹擋住。
所以,問題轉化爲:對於給定的整數 a , b,有多少正整數對 (x,y),滿足x≤a,y≤b,並且gcd(x,y)=1。

前60分,直接gcd(i,j)==1判斷即可(暴力分真多)

後20分,用歐拉函數搞一下就可以了。

最後20分,據說要莫比烏斯反演。(然而並不會)

【代碼】

先給上蒟蒻的60分暴力代碼

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;

LL gcd(LL a,LL b) {
    return b?gcd(b,a%b):a;
}

LL n,m,ans=0;

int main() {
    freopen("indexthree.in","r",stdin);
    freopen("indexthree.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            if(gcd(i,j)==1)
                ans++;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

總結

這次考試竟然沒有炸,真的神啦,會做的竟然沒有炸,太神了!!!

發佈了39 篇原創文章 · 獲贊 7 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章