Summer day 11

今天上午訓練賽,沒有激情,果斷水兩道題。
其實每道題都看過,其他題是真不知道算法。等下午講題後上分析吧。下面是水過的兩題。

POJ 1852 Ants (Also UVa 10714)

題意:一根杆上有幾個螞蟻,爬的方向不確定,且兩隻螞蟻碰頭會反向爬。問所有螞蟻掉下杆的最短和最長時間。
引用大牛分析。

對於每一隻螞蟻,它在棍子上面,距離左端點和右端點的距離可能是相等的也可能是不同的。暫時把距離遠的那端叫做遠端,距離近的那端叫做近端。
那麼爲了使得所有花時間最短,就要讓所有的螞蟻都往近端走,最後總間取決於所有螞蟻中近端最遠的那隻螞蟻,它的時間即是最小時間花費。
同理可推得,要使得所花時間最長,就要讓所有螞蟻都往遠端走,這樣最後長時間取決於所有螞蟻中的遠端最遠的那隻螞蟻。
不用去考慮兩隻螞蟻碰頭的情況, 因爲離遠端最遠的那隻一定是在最右邊或者最左邊的那隻螞蟻,那麼當它往遠端方向走時,可能會碰到迎面走來的,那麼他馬上往回走,對面那隻也往回走走,這就相當於“接力”過程,即對面那隻螞蟻替他走這一段本該由他走的路程(整個過程可能會有無數次“接力”,但最終結果都是一樣的,只是這段最遠路程變成由很多隻螞蟻一起完成)。

以及教訓:開數組解決太弱雞了。讀一個處理一個比較高效。
(主要原因是數組開不下= =)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

inline int max(int a,int b){ return a>b?a:b; }
inline int min(int a,int b){ return a<b?a:b; }

int main(){
    int nCase, len, n, dist;
    scanf("%d",&nCase);
    while(nCase--){
        scanf("%d%d",&len, &n);
        int minLen = -100, maxLen = -100; 
        for(int i=0; i<n; ++i){
            scanf("%d",&dist);
            maxLen = max(maxLen, max(dist, len-dist));
            minLen = max(minLen, min(dist, len-dist));
        }
        printf("%d %d\n", minLen, maxLen);
    }
    return 0;
}

HDU 5512 Pagodas

乍一看博弈論,其實是找規律。
題意:給出長度n和a,b,a,b處有廟,兩人輪流重建剩下的位置,直到不能重建爲止,每次只能選a+b或者a-b處重建。
分析:若奇異情況(6,8),則其等價於(2,6)(即後者可以生成前者),再推可以得(2);若情況(3,7),等價於(3,4),再等價於(1,3),再等價於(1)。

這正是尋找最大公約數的過程!

gcd(a,b)的倍數即是可以重建的位置,故可以通過n/gcd(a, b)-2的奇偶來判斷先手勝負情況。減2是因爲已有兩座塔a,b。

#include<cstdio>

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

void solve(int n, int a, int b)
{
    int p = gcd(a, b);
    int avi = n/p -2;
    if(avi&1) printf("Yuwgna\n");
    else printf("Iaka\n");
}

int main()
{
    int t, kase = 1;
    scanf("%d", &t);
    while(t--)
    {   int n, a, b;
        scanf("%d%d%d", &n, &a, &b);
        printf("Case #%d: ",kase++);
        solve(n, a, b);
    }
    return 0;
}

PS 第二個人叫做Iaka,第一個字母是大寫的i,不是小寫的L·····mdzz害我WA。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章