[noip模拟赛2107.7.3]

题目名称掷骰子环岛旁边铁路历险
源文件名dice.pas/.c/.cpproundabout.pas/.c/.cpprailway.pas/.c/.cpp
输入文件dice.inroundabout.inrailway.in
输出文件dice.outroundabout.outrailway.out
时间限制每个测试点1s每个测试点1s每个测试点2s
内存限制128MB128MB128MB
测试点数目101010
每个测试点分值101010
题目类型传统型传统型传统型
是否有部分分
是否有附加文件
是否有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<N<=50000 ,0<a[i]<=100。

题解

本来以为是概率DP的,仔细一看才发现是个贪心。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int m,n,a[50005];
double ans;
int main(){
    freopen("dice.in","r",stdin);
    freopen("dice.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),m+=a[i];
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=a[i];j++){
            ans+=double(m)/double(a[i]);
            m--;
        }
    }
    printf("%.3lf",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.

题解

模拟,模拟,还是模拟.........................

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s[5][105];int T;
int come[5][105],Car;
int w[5][105],h[5],t[5];
int trs(char ch){
    if(ch=='N')return 1;
    if(ch=='E')return 4;
    if(ch=='S')return 3;
    if(ch=='W')return 2;
    return 0;
}
char rtrs(int num){
    if(num==1)return 'N';
    if(num==2)return 'W';
    if(num==3)return 'S';
    if(num==4)return 'E';
    return ' ';
}
void read(){
    scanf("%s%s%s%s",s[1],s[4],s[3],s[2]);
    for(int i=1;i<=4;i++){
        int len=strlen(s[i]);
        for(int j=0;j<len;j++){
            come[i][j]=trs(s[i][j]);
            if(come[i][j])Car++;
        }       
    }
}
void wait_in(){
    for(int i=1;i<=4;i++)
        if(come[i][T])
            w[i][t[i]++]=come[i][T];
}
int road[5];
void run(){
    int tmp[5];
    for(int i=1;i<=4;i++){
        if(road[i]==i)road[i]=0,Car--;
    }
    for(int i=1;i<=4;i++)tmp[i]=road[i];
    for(int i=1;i<=4;i++){
        int last=i-1;if(last==0)last=4;
        road[i]=tmp[last];
    }
}
int flag[5];
void check(){
    if(h[1]<t[1]&&h[2]<t[2]&&h[3]<t[3]&&h[4]<t[4]){
        flag[1]=false;flag[2]=false;
        flag[3]=false;flag[4]=false; 
        if(road[4]==0)flag[1]=true;
        return;
    }
    for(int i=1;i<=4;i++){
        int last=i-1;if(last==0)last=4;
        if(h[i]>=t[i]){
            flag[i]=false;
            continue;
        }
        if(h[last]<t[last]||road[last])flag[i]=false;
        else flag[i]=true;
    }
}
void wait_out(){
    for(int i=1;i<=4;i++)if(flag[i])
        road[i]=w[i][h[i]++];
}
void Debug(){
    cout<<T<<endl;
    cout<<"    "<<'|'<<rtrs(w[1][h[1]])<<'|'<<"    "<<endl;
    cout<<"    "<<"/"<<" \\"<<"    "<<endl;
    cout<<"   "<<"/ " <<rtrs(road[1])  <<" \\"<<"   "<<endl;
    cout<<" --"<<" /-\\ "              <<"-- "<<endl;
    cout<<" "<<rtrs(w[2][h[2]])<<" "<<rtrs(road[2])<<"| |"<<rtrs(road[4])<<" "<<rtrs(w[4][h[4]])<<endl;
    cout<<" --"<<" \\-/ "              <<"-- "<<endl;
    cout<<"   "<<"\\ " <<rtrs(road[3])  <<" /"<<"   "<<endl;
    cout<<"    "<<"\\"<<" /"<<"    "<<endl;
    cout<<"    "<<'|'<<rtrs(w[3][h[3]])<<'|'<<"    "<<endl;
}
void work(){
    while(Car){
        wait_in();
        //Debug();
        check();
        run();
        wait_out();
        T++;
    }
}
void print(){
    printf("%d",T);
}
int main(){
    freopen("roundabout.in","r",stdin);
    freopen("roundabout.out","w",stdout);
    read();
    work();
    print();
} 

铁路历险 (railway.pas/.c/.cpp)

题目描述

经过一番努力,Freda 和 Rainbow 来到了魔力铁路的 1 号站台。它们知道,魔力铁路不
同于普通的铁路,下面有一段关于魔力铁路的介绍。
魔力铁路一共有N座站台,从第i(1<i<=N)号站台出发可以到达第i-1号站台。同时,对
于每个i(1<=i<=N),你需要规定x[i]为1~N当中的任意一个数字,表示从第i号站台出发可
以到达的另外一个站台,当然,你也可以把x[i]规定为i或者i-1。
Rainbow 和 Freda 想知道,有多少种不同的规定 x[i]的方案,使得它们能够到达 N 号站
台呢?方案A、B不同的条件是:存在一个i(1<=i<=N)使得方案A中的x[i]与方案B中的
x[i]不同。Freda 最讨厌乱七八糟的上万位数字了,所以,记得把答案 mod 1000000007
(10^9+7)哦lala~

输入格式

一行一个整数N,表示站台的总数。

输出格式

一行一个整数Ans,表示Freda和Rainbow能够到达N号站台的方案数。

样例输入

3

样例输出

12
样例解释
12种可能的方案如下(每行代表一种方案):

x[1]x[2]x[3]
231
232
233
311
312
313
321
322
323
331
332
333

数据范围与约定

对于30%的数据,N<=5.

对于50%的数据,N<=10.

对于70%的数据,N<=100.

对于100%的数据,0<N<=5000.

题解

设只能到达i的答案为f[i],不难发现以下规律:

image

大意就是把前i个车站连通总方案减去只能到达前i-1个车站的方案,得到的就是f[i],即只能到达第i个车站的方案数

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL int
#define mod 1000000007
using namespace std;
LL n;
LL ans[5005];
LL ksm[5005][5005];

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

转载于:https://www.cnblogs.com/Anoxiacxy/p/7135787.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值