kickstart 2020B

Bike Tour

Problem
Li has planned a bike tour through the mountains of Switzerland. His tour consists of N checkpoints, numbered from 1 to N in the order he will visit them. The i-th checkpoint has a height of Hi.

A checkpoint is a peak if:
It is not the 1st checkpoint or the N-th checkpoint, and
The height of the checkpoint is strictly greater than the checkpoint immediately before it and the checkpoint immediately after it.

Please help Li find out the number of peaks.

Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a line containing the integer N. The second line contains N integers. The i-th integer is Hi.

Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the number of peaks in Li’s bike tour.

水题

#include<iostream>
#include<cstdio>
#define MAXN 110
using namespace std;
int T,iCase,n,a[MAXN];
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        int res = 0;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=2;i<n;i++)
            if(a[i]>a[i-1]&&a[i]>a[i+1])
                res++;
        printf("Case #%d: %d\n",++iCase,res);
    }
    return 0;
}

Bus Routes 倒推DP

Problem
Bucket is planning to make a very long journey across the countryside by bus. Her journey consists of N bus routes, numbered from 1 to N in the order she must take them. The buses themselves are very fast, but do not run often. The i-th bus route only runs every Xi days.

More specifically, she can only take the i-th bus on day Xi, 2Xi, 3Xi and so on. Since the buses are very fast, she can take multiple buses on the same day.

Bucket must finish her journey by day D, but she would like to start the journey as late as possible. What is the latest day she could take the first bus, and still finish her journey by day D?

It is guaranteed that it is possible for Bucket to finish her journey by day D.

Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a line containing the two integers N and D. Then, another line follows containing N integers, the i-th one is Xi.

Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the latest day she could take the first bus, and still finish her journey by day D.

#include<iostream>
#include<cstdio>
#define MAXN 1010
using namespace std;
typedef long long ll;
int T,n,iCase;
ll d,a[MAXN];
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    scanf("%d",&T);
    while(T--){
        scanf("%d%lld",&n,&d);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        for(int i=n;i>=1;i--){
            ll cd=d/a[i]*a[i];
            d=cd;
        }
        printf("Case #%d: %lld\n",++iCase,d);
    }
    return 0;
}

Robot Path Decoding 递归展开

Problem
Your country’s space agency has just landed a rover on a new planet, which can be thought of as a grid of squares containing 109 columns (numbered starting from 1 from west to east) and 109 rows (numbered starting from 1 from north to south). Let (w, h) denote the square in the w-th column and the h-th row. The rover begins on the square (1, 1).

The rover can be maneuvered around on the surface of the planet by sending it a program, which is a string of characters representing movements in the four cardinal directions. The robot executes each character of the string in order:
N: Move one unit north.
S: Move one unit south.
E: Move one unit east.
W: Move one unit west.
There is also a special instruction X(Y), where X is a number between 2 and 9 inclusive and Y is a non-empty subprogram. This denotes that the robot should repeat the subprogram Y a total of X times. For example:
2(NWE) is equivalent to NWENWE.
3(S2(E)) is equivalent to SEESEESEE.
EEEE4(N)2(SS) is equivalent to EEEENNNNSSSS.

Since the planet is a torus, the first and last columns are adjacent, so moving east from column 109 will move the rover to column 1 and moving south from row 109 will move the rover to row 1. Similarly, moving west from column 1 will move the rover to column 109 and moving north from row 1 will move the rover to row 109. Given a program that the robot will execute, determine the final position of the robot after it has finished all its movements.

Input
The first line of the input gives the number of test cases, T. T lines follow. Each line contains a single string: the program sent to the rover.

Output
For each test case, output one line containing Case #x: w h, where x is the test case number (starting from 1) and w h is the final square (w, h) the rover finishes in.

需要递归求解,处理 3(W…) 这种情况时要把每个重复的部分总的偏移算好,然后乘上前面的重复次数,否则重复展开计算的话会超时。要注意步步取模,两个数相乘有可能溢出的地方乘上 long long ,不然会 WA。

#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
#include<utility>
#define M 1000000000
#define MAXN 2010
#define mp(x,y) make_pair<int,int>(x,y)
using namespace std;
typedef long long ll;
int T,iCase,n,w,h;
char s[MAXN],tmp[MAXN];
pair<int,int> cp;
pair<int,int> proc(int l,int r){
    int dx=0,dy=0;
    if(l>r)return mp(0,0);
    if(!isdigit(s[l])){
        if(s[l]=='N')h=(h+M-1)%M,dy--;
        if(s[l]=='S')h=(h+1)%M,dy++;
        if(s[l]=='E')w=(w+1)%M,dx++;
        if(s[l]=='W')w=(w+M-1)%M,dx--;
        cp=proc(l+1,r);
        return mp((dx+cp.first)%M,(dy+cp.second)%M);
    }else{
        int k=s[l]-'0';
        int p=l+2;
        stack<char> t;
        t.push('(');
        while(!t.empty()){
            p++;
            if(s[p]=='(')t.push('(');
            if(s[p]==')')t.pop();
        }
        cp=proc(l+2,p-1);
        h=(h+M+1ll*cp.second*(k-1)%M)%M;
        w=(w+M+1ll*cp.first*(k-1)%M)%M;
        dx=1ll*cp.first*k%M;dy=1ll*cp.second*k%M;
        cp=proc(p+1,r);
        return mp((dx+cp.first)%M,(dy+cp.second)%M);
    }
}
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    scanf("%d",&T);
    while(T--){
        scanf(" %s ",s);
        w=0;h=0;n=strlen(s);
        proc(0,n-1);
        printf("Case #%d: %d %d\n",++iCase,w+1,h+1);
    }
    return 0;
}

Wandering Robot 概率DP+改进

Problem
Jemma is competing in a robotics competition. The challenge for today is to build a robot that can navigate around a hole in the arena.

The arena is a grid of squares containing W columns (numbered 1 to W from left to right) and H rows (numbered 1 to H from top to bottom). The square in the x-th column and y-th row is denoted (x, y). The robot begins in the top left square (1,1) and must navigate to the bottom right square (W, H).

A rectangular subgrid of squares has been cut out of the grid. More specifically, all the squares that are in the rectangle with top-left square (L, U) and bottom-right square (R, D) have been removed.

Jemma did not have much time to program her robot, so it follows a very simple algorithm:
If the robot is in the rightmost column, it will always move to the square directly below it. Otherwise,
If the robot is in the bottommost row, it will always move to the square directly right of it. Otherwise,
The robot will randomly choose to either move to the square directly to the right, or to the square directly below it with equal probability.

Jemma passes the challenge if her robot avoids falling into the hole and makes it to the square (W, H). What is the probability she passes the challenge?

Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case consists of a single line containing W, H, L, U, R and D.

Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is a real number between 0 and 1 inclusive, the probability that Jemma passes the challenge.

y will be considered correct if it is within an absolute or relative error of 10-5 of the correct answer. See the FAQ for an explanation of what that means, and what formats of real numbers we accept.

概率DP

概率DP很好写

#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 100010
using namespace std;
int T,iCase,W,H,L,U,R,D;
double dp[MAXN];
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d%d%d%d",&W,&H,&L,&U,&R,&D);
        memset(dp,0,sizeof(dp));
        for(int i=D;i>=1;i--)
            for(int j=R;j>=1;j--){
                if(i>=U&&j>=L){dp[j]=1;continue;}
                if(i==H)dp[j]=dp[j+1];
                else if(j==W)dp[j]=dp[j];
                else dp[j]=0.5*dp[j]+0.5*dp[j+1];
            }
        printf("Case #%d: %.6lf\n",++iCase,1-dp[1]);
    }
    return 0;
}

O(n) 改进

这个改进的解释可以参考官方分析,但是仅仅那样实现是不够的。如下图,假如在右上角碰到仍然向上的边界是需要计算图中每个红格子的到达概率,斜对角上红格子概率的计算参见官方 analysis,再往上的格子(用红圈圈起来的)用相同的方法计算好概率之后要再除以2,因为对角上的格子不可能同时出现在一条路径上,而向上的格子其产出的路径数分别被包含在其下面的格子概率内以及到其右边的格子。我们只需要再加上到其右边部分的概率即可,因此要除以 2。左下角的格子同理。
在这里插入图片描述

#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#define MAXN 100010
using namespace std;
int T,iCase,W,H,L,U,R,D;
double lg2[MAXN];
void init(){
    lg2[1]=0;lg2[2]=1;
    for(int i=3;i<MAXN;i++)
        lg2[i]=lg2[i-1]+log2(i);
}
double proc(int n,int k){
    // C(n,k)/2^n=2^(log(n!)-log((n-k)!)-log(k!)-n)
    double up=lg2[n]-lg2[n-k]-lg2[k]-n;
    double res=pow(2,up);
    return res;
}
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    init();
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d%d%d%d",&W,&H,&L,&U,&R,&D);
        double res=0;double d=1;
        if(R<W){
        for(int i=U-1,j=R+1;i>=1;i--,j++){
            if(j>=W)j=W-1,d=0.5;else d=1;
            res+=proc(i+j-2,j-1)*d;
        }
        }
        if(D<H){
        for(int i=D+1,j=L-1;j>=1;i++,j--){
            if(i>=H)i=H-1,d=0.5;else d=1;
            res+=proc(i+j-2,i-1)*d;
        }
        }
        printf("Case #%d: %.6lf\n",++iCase,res);
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值