首页 > 代码库 > [noip模拟2017.7.3]

[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]