【2022 牛客多校】第九场 B 【数组的存取速度related to cache】

链接

https://ac.nowcoder.com/acm/contest/33194/B

题意是n片荷叶排成一排,两个人都可以从1出发,每次可以从第i片荷叶跳到位置在[i+1,i+a[i]]中的荷叶,问两个人跳到n时具有相同步数的概率是多少

思路

dp[k][i]表示跳了k次后到达位置i的概率,依据乘法原理,ans = \(\sum_{i=1}^n dp[i][n]^2\)

枚举i、次数k、下一个位置j是时间复杂度是 \(O(n^3\)) 的(will get a tle)

所以考虑优化时间,在这里我使用了差分数组

p.s.更新时必须让二维数组值频繁更改的那一维放在内循环的位置,这与cache的工作方式有关,如果不这样做仍然会tle

代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

inline int rd() {
  int x = 0;
  bool f = 0;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) f |= (c == '-');
  for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
  return f ? -x : x;
}

#define N 8007
#define mod 998244353
ll inv[N], f[N][N], a[N];

int main() {
    inv[0] = inv[1] = 1;
    int n = rd();
    for (int i = 2; i <= n; ++i) inv[i] = (mod - mod / i + mod) % mod * inv[mod % i] % mod;
    for (int i = 1; i < n; ++i) a[i] = rd();
    f[0][1] = 1;

    for(int k=1;k<n;k++){
        for(int i=1;i<n;i++){
            ll tem = f[k-1][i] * inv[a[i]] % mod;
            f[k][i+1] = (f[k][i+1] + tem) % mod;
            f[k][i+a[i]+1] = (f[k][i+a[i]+1] - tem + mod) % mod;
        }
        for(int i=1;i<=n;i++) f[k][i] = (f[k][i] + f[k][i-1]) % mod; 
    }

    ll ans = 0;
    for (int i = 1; i <= n; ++i) ans = (ans + 1ll * f[i][n] * f[i][n] % mod) % mod;
    printf("%lld\n", ans);
    system("pause");
    return 0;
}

posted @ 2022-08-15 20:09  starlightlmy  阅读(56)  评论(0)    收藏  举报