CF Round597 Div.2

C. Constanze’s Machine

题意:有一个键盘,你敲w的时候就弹出uu,你敲m的时候就弹出nn,其他正常。现在给你一个用该键盘敲出的字符串,问你原字符串有多少种可能。

思路:首先字符串中不可能出现w和m。对于连续的u和n,用dp求出这一段可能对应的原字符串个数。然后乘起来就好了。

D. Shichikuji and Power Grid

题意:有n个城市, n ≤ 200 n\leq 200 n200,每个城市的坐标为 ( x i , y i ) (x_i,y_i) (xi,yi),你可以在一个城市花费 c i c_i ci 建造供电站,也可以通过修路把两个城市连接起来共享供电站,修路的花费是 ( k i + k j ) ∗ ( ∣ x i − x j ∣ + ∣ y i − y j ∣ ) (k_i+k_j)*(|x_i-x_j|+|y_i-y_j|) (ki+kj)(xixj+yiyj),要求所有城市都能用上电的最小代价。

思路:首先, c c c 最小的城市一定要自己建供电站。接着有两种做法:1. 建完最小代价的城市后,用修路的代价更新其他城市的代价。此时,选取最小代价城市的结论依然成立,递归地添加所有城市;2. 建图,共n+1个节点,城市标号1-n,每个城市引一条边到0号节点,边权为c;城市内部边依据修路代价,求最小生成树。因为是完全图,推荐prim。两种做法复杂度均为 O ( n 2 ) O(n^2) O(n2)

E. Hyakugoku and Ladders

题意:有一个10*10的迷宫,你起初在左下角(0,0)位置,目标在(9,9)。在一个回合中你扔一个1-6的均匀骰子,结果为r你就前进r步,如果前进不了r步(超出迷宫边界)就呆在原地。前进规则有两条:

  1. 在一行内部前进,跨行时不同行之间蛇形排列,因此(9,9)是在左上角
  2. 有的位置有电梯,在前进r步之后你可以选择是否乘坐电梯,每个电梯有高度h,乘坐电梯意味着从(i,j)瞬移到(i+h,j)。乘坐电梯算在当前回合内。

问:从(0,0)到(9,9)所需回合数的期望。

思路:首先按蛇形给10*10方格里的位置标号0-99,用dp[i]表示从i号位置到达目标的期望操作数,dp[99]=0,答案就是dp[0]。假如没有电梯,我们身处i号位置,投骰子6种结果中有cnt种结果会让我们前进。那么:
d p [ i ] = 1 + 1 6 ⋅ ( Σ j = 1 c n t d p [ i + j ] + Σ j = 1 6 − c n t d p [ i ] ) dp[i]=1+\frac{1}{6}\cdot(\Sigma_{j=1}^{cnt}dp[i+j]+\Sigma_{j=1}^{6-cnt}dp[i]) dp[i]=1+61(Σj=1cntdp[i+j]+Σj=16cntdp[i])
整理一下: d p [ i ] = 1 c n t ⋅ ( 6 + Σ j = 1 c n t d p [ i + j ] ) dp[i]=\frac{1}{cnt}\cdot(6+\Sigma_{j=1}^{cnt}dp[i+j]) dp[i]=cnt1(6+Σj=1cntdp[i+j])

如果有电梯的话,我们用f[i]表示i号位置乘坐电梯后的位置编号(如果该位置没有电梯,f(i)=i),将上式中的dp[i+j]都替换为min(dp[i+j], dp[f[i+j]])即可。

F. Daniel and Spring Cleaning

题意:给你两个数 l , r , 0 ≤ l ≤ r ≤ 1 0 9 l,r, 0\leq l\leq r\leq 10^9 l,r,0lr109。问有多少对(x,y)满足 l ≤ x , y ≤ r , x + y = x   x o r   y l\leq x,y\leq r,x+y=x\ xor\ y lx,yrx+y=x xor y

分析:首先,两个数相加和异或的结果相同,等价于按位与的结果为0。根据最后一位只能是(0,0),(0,1),(1,0),我们可以得到 a n s ( 2 l , 2 r ) = 3 ⋅ a n s ( l , r ) ans(2l,2r)=3\cdot ans(l,r) ans(2l,2r)=3ans(l,r)。这里为了映射方便,ans(x,y)定义左闭右开的区间[x,y)上满足要求的pair数。
所以,当x,y都是偶数时,我们可以递归求解ans(x,y)。如果x,y中有奇数的话,把边界单独处理就行了。在处理奇数的时候,需要一个函数f(x,y)高效地统计[0,y)区间内和x按位与结果为0的数的个数,实现如下:

int f(int a, int b) {
  int ret = 0, zeroes = 0;
  for (int i = 1; i <= b; i <<= 1) {
    if (b & i) {
      b ^= i;
      if (!(a & b)) ret += (1 << zeroes);
    }
    if (!(a & i)) zeroes++;
  }
  return ret;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值