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;
}