Codeforces Good Bye 2017

A. New Year and Counting Cards
题意:牌的正面是数字反面是字母,要判断是否所有的元音字母背面都是偶数。

题解:需要翻的牌是所有的元音字母与奇数。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;

int n;
char a[maxn];
int main()
{

    scanf("%s", a);
    n = strlen(a);
    int ans = 0;
    for (int i = 0; i < n; i++)
    {
        if (a[i] >= '0'&&a[i] <= '9')
        {
            if ((a[i] - '0') % 2 == 1)ans++;
        }
        else
        {
            if (a[i] == 'a' || a[i] == 'e' || a[i] == 'i' || a[i] == 'o' || a[i] == 'u')ans++;
        }
    }
    printf("%d\n", ans);
    return 0;
}

B.New Year and Buggy Bot
题意:在一个二维迷宫里要从起点走到终点。路径可以用一串数字表示,其中1-4分别表示上下左右中的一个方向。现在数字与路径的对应关系是未知的,问有多少种可能可以在这串数字的范围之内从起点走到终点。

题解:总共的方案数是4!=24种,串的长度也只有50,直接遍历一遍所有的组合就行了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#define maxn 105
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;

int n, m, l, sx, sy;
char maze[maxn][maxn];
int p[25][4] = {0,1,2,3,0,2,1,3,0,3,1,2,0,3,2,1,0,1,3,2,0,2,3,1,2,1,3,0,2,1,0,3,2,3,0,1,2,3,1,0,2,0,1,3,2,0,3,1,1,2,3,0,1,2,0,3,1,3,0,2,1,3,2,0,1,0,2,3,1,0,3,2,3,0,1,2,3,0,2,1,3,2,1,0,3,2,0,1,3,1,2,0,3,1,0,2 };
char w[maxn];
bool judge(int x, int y)
{
    if (x >= 0 && x < n&&y >= 0 && y < m&&maze[x][y] != '#')return true;
    return false;
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++)
    {
        scanf("%s", maze[i]);
        for (int j = 0; j < m; j++)
            if (maze[i][j] == 'S')sx = i, sy = j;
    }
    scanf("%s", w);
    l = strlen(w);
    int ans = 0;
    for (int i = 0; i < 24; i++)
    {
        int nx = sx, ny = sy;
        int flag = 0;
        for (int j = 0; j < l; j++)
        {
            int cnt = w[j] - '0';
            if (p[i][cnt] == 0)ny--;
            else if (p[i][cnt] == 1)ny++;
            else if (p[i][cnt] == 2)nx--;
            else nx++;
            if (!judge(nx, ny))break;
            if (maze[nx][ny] == 'E')
            {
                ans++;
                break;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

C.New Year and Curling
题意:从正方向依次向轴推冰壶,当后面的冰壶接触到前面的冰壶时就会立刻停止运动,已知所有冰壶的初始横坐标与半径,求所有冰壶圆心在最后的纵坐标。

题解:冰壶的横坐标是不会变的,也不考虑碰撞的速度变化,直接从前往后扫一遍就好了。注意当两个冰壶相切的时候也算接触到。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#define maxn 1005
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;

int n;
double r;
double x[maxn];
double y[maxn];

double sq(double a, double b)
{
    return sqrt(a*a - b*b);
}

int main()
{
    scanf("%d%lf", &n, &r);
    for (int i = 0; i < n; i++)
        scanf("%lf", &x[i]);
    y[0] = r;
    for (int i = 1; i < n; i++)
    {
        double maxx = r;
        for (int j = 0; j < i; j++)
        {
            if (fabs(x[i] - x[j]) > 2*r)continue;
            maxx = max(maxx, y[j] + sq(2 * r, fabs(x[i] - x[j])));
        }
        y[i] = maxx;
    }
    for (int i = 0; i < n; i++)
        printf(i == n - 1 ? "%.10lf\n" : "%.10lf ", y[i]);

    return 0;
}

D.New Year and Arbitrary Arrangement
题意:有一个字符串,初始为空。
有Pa/Pa+Pb的概率在末尾添加字母a,有 Pb/Pa+Pb的概率在末尾添加字母b,当出现≥k个ab子串时立即停止添加字母,求最后期望的ab子串个数。(子串ab不要求连续)

题解:概率DP。dp[i][j]表示串的前缀中有i个a和j个ab子串时,ab子串的期望个数。当在前缀后面添上a时有dp[i][j]=dp[i+1][j]*pa/(pa+pb),当在前缀后面添上b时有dp[i][j]=dp[i][j+i]*pb/(pa+pb)。
于是得到了状态转移方程:dp[i][j]= dp[i+1][j]*pa/(pa+pb)+dp[i][j+i]*pb/(pa+pb)。
接下来就要确定目标状态和初始状态,这里就需要考虑两种无穷的情况:
1. 前缀出现了无穷多个b。显然在第一个a之前的所有的b都没有任何用处。要结束这个串就必须出现一个a并且没有ab的状态,因此目标状态定为dp[1][0]。
2. 出现了无穷多个a。虽然这样概率很小但是会出现很多的ab不可忽略,如果直接递推会让结果趋于无穷大,因此我们单独对i+j很大时的期望进行近似计算。
分析可得dp[i][j]可以表示为

使用错位相减法可以求得结果为i+j+pa/pb。于是初始值就是i+j>=k时的dp[i][j]= i+j+pa/pb。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#define maxn 1050
#define INF 0x3f3f3f3f
#define eps 1e-8
const int mod=1e9+7;
using namespace std;
typedef long long ll;

int k,a,b,pa,pb;
int dp[maxn][maxn];

void ex_gcd(int a,int b,int &x,int &y)
{
    if(b==0)x=1,y=0;
    else
    {
        ex_gcd(b,a%b,y,x);
        y-=x*(a/b);
    }
}
int inv(int a)
{
    int x,y;
    ex_gcd(a,mod,x,y);
    return (x%mod+mod)%mod;
}

int main()
{
    scanf("%d%d%d",&k,&a,&b);
    pa=(1LL*a*inv(a+b))%mod;
    pb=(1-pa+mod)%mod;
    int cnt=(1LL*a*inv(b))%mod;
    for(int i=k;i>=1;i--)
    {
        for(int j=k;j>=0;j--)
        {
            if(i+j>=k)dp[i][j]=(i+j+cnt)%mod;
            else dp[i][j]=((1LL*pa*dp[i+1][j])%mod+(1LL*pb*dp[i][i+j])%mod)%mod;
        }
    }
    printf("%d\n",dp[1][0]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值