[noip模擬2017.7.3]
題目名稱 | 擲骰子 | 環島旁邊 | 鐵路歷險 |
---|---|---|---|
源文件名 | 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]