1. 程式人生 > >[noip模擬2017.7.3]

[noip模擬2017.7.3]

題解 評測 mes 遞推 include algo ostream mar 第三題

題目名稱擲骰子環島旁邊鐵路歷險
源文件名 dice.pas/.c/.cpp roundabout.pas/.c/.cpp railway.pas/.c/.cpp
輸入文件 dice.in roundabout.in railway.in
輸出文件 dice.out roundabout.out railway.out
時間限制 每個測試點1s 每個測試點1s 每個測試點2s
內存限制 128MB 128MB 128MB
測試點數目 10 10 10
每個測試點分值 10 10 10
題目類型 傳統型 傳統型 傳統型
是否有部分分
是否有附加文件
是否有Special Judge

評測環境:Windows7, Intel(R) Core(TM) i5-2430M CPU @ 2.40GHz

註意:最終評測時,所有編譯命令均不打開任何優化開關!

擲骰子(dice.pas/.c/.cpp)

題目描述

Rainbow和Freda通過一次偶然的機會來到了魔界。魔界的大門上赫然寫著:
小盆友們,歡迎來到魔界!乃們需要解決這樣一個問題才能進入哦lala~
有 N 枚骰子,其中第 i(1<=i<=N)枚骰子有 a[i]面。擲出第 i 枚骰子時,這 a[i]面中只
有一面朝上,而且這a[i]面每面朝上的概率都相等,為1/a[i].
門上還寫道:這N個骰子,顯然一共有M = ∑ ??[??] ?? ??=1 個面。你們要做的就是把1~M這M
個數字不重不漏地寫到這M個面上。同時擲出這N個骰子,你們的得分就是這N個骰子朝上
的面上的數字之和。你們要做的,就是使你們的得分的期望值最大哦~

輸入格式

第一行一個整數N,表示骰子的數目。

第二行N個整數,第i個整數a[i]表示第i個骰子有多少個面。

輸出格式

一行一個實數Ans,表示Freda和Rainbow得分的最大期望值,保留三位小數。

樣例輸入

2
1 4

樣例輸出

7.500

樣例解釋

在第一個骰子的唯一一面寫上 5,第二個骰子的四面分別寫上 1,2,3,4。這樣得分的期望就
是5/1+(1+2+3+4)/4=7.5了。

數據範圍與約定

對於30%的數據,N<=10

對於50%的數據,N<=1000.

對於100%的數據,0

題解

送分的…

#include <iostream>
#include <cstdio>
#include <cstring> #include <algorithm> #define N 50010 using namespace std; int a[N]; int main() { freopen("dice.in","r",stdin); freopen("dice.out","w",stdout); int n,tot=0; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); tot+=a[i]; } sort(a+1,a+1+n); int cnt=tot;double ans=0; for(int i=1;i<=n;i++) { int num=0; for(int j=1;j<=a[i];j++) { num+=cnt; cnt--; } ans+=(double)num/a[i]; } printf("%.3f",ans); return 0; }

環島旁邊 (roundabout.pas/.c/.cpp)

題目描述

Rainbow 和 Freda 在擲骰子的時候 rp 爆發,居然擲出了滿點><(其實我就不說所有的
a[i]都是1),順利到達了環島旁。它們正觀察著這個環島的時候,環島居然開口說話了T_T:
歡迎來到魔界環島。我會告訴你們環島的運行方式,並且邀請你們幫我解決一個問題。環
島在東西南北四個方向分別有一個入口和出口,環島內的車輛逆時針行駛。車輛可以進入、離
開或環島或者在環島內行進一步,這三種操作每次都是耗時1秒。在環島內行進一步,即從東
走到北,從北走到西,從西走到南或者從南走到東(換句話說,行進兩步就可以圍繞環島走半
圈了)。如果操作不互相幹擾,所有車輛的操作可以同時進行。比如,環島上有兩輛車,一輛
在另一輛的後面,它們可以一起在環島內行進一步。一輛車是否進入環島取決於它們這一秒是
否可以進入,如果此時可以進入,它一定會進入,否則就將加入或者停留在該方向的等待序列
中。
什麽時候一輛車可以進入環島呢?這取決於它上一秒得到的信息。如果第 i-1 秒時,它所
在方向的順時針緊鄰方向的環島上和等待序列裏面都沒有車,而且它是所在方向等待序列的第
一輛車,那麽它在第i秒可以進入環島。特別地,四個方向的等待序列裏都有車的時候,北面
的車優先行駛——即只要第i-1秒時東面環島上沒有車,第i秒的時候,北面等待的第一輛車
就可以進入環島了。
當然,每個車輛都有一個目標方向,一旦一輛車A到達了目標方向,它就會馬上離開環島
的。註意,如果此時它的目標方向有另一輛車B在等待進入環島且B車此時可以進入環島,A
車離開環島和B車進入環島是發生在同一秒的。
“我將給你們每秒車輛到達環島旁的信息,請你們幫我計算,最後一輛車離開環島的時間
好嗎?”

輸入格式

四行,每行一個字符串。
第一行一個字符串N,只含有‘-’,‘S’,‘W’,‘E’四種字符,字符串的第i個字符N[i]
表示第i-1秒的時候,有一輛來自北方向、目標方向為N[i]的車等待進入環島,如果N[i]=’-',
表示第i-1秒沒有車來自北方向。
第二行一個字符串E,只含有 ‘-’,‘ S’,‘W’,‘N’四種字符,含義同上。
第三行一個字符串S,只含有 ‘-’,‘ N’,‘W’,‘E’四種字符,含義同上。
第四行一個字符串W,只含有 ‘-’,‘ S’,‘N’,‘E’四種字符,含義同上。
對於字符串中的字符,N表示北方向,E表示東方向,W表示西方向,S表示南方向。

輸出格式

一行一個整數totalTime,表示最後一輛車離開環島的時間。

樣例輸入1

WE

-S

樣例輸出1

6

樣例輸入2

ES

N

E

樣例輸出2

9

樣例解釋

樣例1如圖所示:

數據範圍與約定 對於50%的數據,每個字符串長度<=10.
對於100%的數據,0<每個字符串長度<=100.

題解

第二題其實算是有一點復雜的摸擬吧,因為那個時間真的很煩人,但是思路清晰的學長基本上都是寫好分函數,很清楚,這樣寫模擬不會錯!!但是我當shi還是分析了一下基本的情況,每輛車都只是在進圈的時候受到限制,此後便不再,所以進圈的時間知道那麽結束時間你也很清楚。所以可能對於我來說就比較好想了

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

using namespace std;

char ch[5][110];
int ans=-1,tim=0,flag[5],a[5][110],b[5][100000],len[5];

int translate(char x)
{
    if(x==‘N‘)return 1;
    else if(x==‘E‘)return 2;
    else if(x==‘S‘)return 3;
    else if(x==‘W‘)return 4;
    else if(x==‘-‘)return 5;
    else return 0;
}

int findf(int x)
{
    for(int i=0;;i++)
    {
        if(i<=tim&&a[x][i]!=5)
            return i;
        if(i>=tim)break;
    }
    return tim;
}

bool judge()
{
    for(int i=1;i<=4;i++)
    {
        for(int j=0;j<len[i];j++)
            if(a[i][j]!=5)return false;
    }
    return true;
} 
int deal(int from,int to)
{
    if(from>to)
    {
        int stim=tim+1;
        for(int i=from;i>=to;i--)
            b[i][stim]++,stim++;
        return from-to+2;
    }
    if(from<=to)
    {
        int stim=tim+1;
        int num=from+4-to;
        for(int i=0;i<=num;i++)
        {
            int pos=from-i;
            if(pos<=0)pos+=4;
            b[pos][stim]++;
            stim++;
        }
        return from+4-to+2;
    }
}

bool check(int x1,int x2,int x3,int x4)
{
    if(a[1][x1]==0||a[2][x2]==0||a[3][x3]==0||a[4][x4]==0)return false;
    if(a[1][x1]==5||a[2][x2]==5||a[3][x3]==5||a[4][x4]==5)return false;
    if(b[2][tim])return false;
    return true;
}

void clear()
{
    for(int i=1;i<=4;i++)
    b[i][tim-1]=0,flag[i]=-1;
}

void update()
{
    int p1=findf(1);int p2=findf(2); 
    int p3=findf(3);int p4=findf(4);
    if(p2>len[2]-1)a[2][p2]=5;
    if(a[1][p1]!=5&&a[1][p1]!=0)
    {
        if(!b[2][tim]&&a[2][p2]==5||check(p1,p2,p3,p4))
        {
            int finish=deal(1,a[1][p1]);
            ans=max(ans,finish+tim);
            flag[1]=p1;
        }
    }
    for(int i=1;i<=4;i++)
    {
        int pos1=findf(i),pos2=findf(i%4+1);
        if(pos2>len[(i%4+1)]-1)a[i%4+1][pos2]=5;
        if(a[i][pos1]!=5&&a[i][pos1]!=0)
        {
            if(a[i%4+1][pos2]==5&&!b[i%4+1][tim])
            {
                int finish=deal(i,a[i][pos1]);
                ans=max(ans,finish+tim);
                flag[i]=pos1;
            }
        }
    }
}
int main()
{
    //freopen("roundabout.in","r",stdin);
    //freopen("roundabout.out","w",stdout);
    scanf("%s%s%s%s",ch[1],ch[2],ch[3],ch[4]);
    for(int i=1;i<=4;i++)
    {
        len[i]=strlen(ch[i]);
        for(int j=0;j<len[i];j++)
            a[i][j]=translate(ch[i][j]);
    }
    while(true)
    {
        clear();
        update();
        tim++;
        if(judge())break;
    }
    cout<<ans;
    return 0;
}

鐵路歷險

(railway.pas/.c/.cpp)

題目描述

經過一番努力,Freda 和 Rainbow 來到了魔力鐵路的 1 號站臺。它們知道,魔力鐵路不
同於普通的鐵路,下面有一段關於魔力鐵路的介紹。
魔力鐵路一共有N座站臺,從第i(1

輸入格式

一行一個整數N,表示站臺的總數。

輸出格式

一行一個整數Ans,表示Freda和Rainbow能夠到達N號站臺的方案數。

樣例輸入

3

樣例輸出

12
樣例解釋
12種可能的方案如下(每行代表一種方案):

x[1]x[2]x[3]
2 3 1
2 3 2
2 3 3
3 1 1
3 1 2
3 1 3
3 2 1
3 2 2
3 2 3
3 3 1
3 3 2
3 3 3

數據範圍與約定

對於30%的數據,N<=5.

對於50%的數據,N<=10.

對於70%的數據,N<=100.

對於100%的數據,0

題解

第三題真的是數學不行,其實就是對情況的歸納吧,總方案-不合理方案,不合理的方案是只能到達終點前的點的情況,而這些情況也正好是前者的方案數,於是真的可以遞推…..然後滾動數組可以用起來(沒怎麽打比較生)

技術分享

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define mod 1000000007
using namespace std;

int mic[5005][5005];
int ans[5005];

int main()
{
    freopen("railway.in","r",stdin);
    freopen("railway.out","w",stdout);
    int n;scanf("%d",&n);
    ans[1]=1,ans[2]=2;
    for(int i=1;i<=n;i++)
    {
        mic[i][0]=1;
        for(int j=1;j<=i;j++)
            mic[i][j]=((1LL)*mic[i][j-1]*i)%mod;
    }
    for(int i=3;i<=n;i++)
    {
        ans[i]=mic[i][i];
        for(int j=1;j<=i-1;j++)
            ans[i]=(ans[i]+mod-((1LL)*mic[i][i-j]*ans[j])%mod)%mod;
    }
    cout<<ans[n];
    return 0;
}

[noip模擬2017.7.3]