题解 | #B - Two Frogs#

Two Frogs

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

Two Frogs

题目描述

In the Lonely Mountain, there are a lot of treasure well protected by dwarfs. Later, one day, the last dragon Smaug came and sensed the treasure being. As known to all, dragons are always much too greedy for treasure. So definitely, the war between dwarfs and Smaug begins.

During the war, two goblins Alice and Bob are turned into frogs by Gandalf, The Grey. In front of them, there are nn lotus leaves in a line. In order to break the spell, they must jump from the 11 - st lotus leaf to the nn-th lotus leaf. If the frog is now on the ii-th lotus leaf instead of the nn - th lotus leaf, it can jump to a lotus leaf in range (i,i+ai](i, i + a_i] .

Goblins are lack of intelligence and it's also true even after turned into frogs. So Alice and Bob will jump randomly, which means, they will separately pick an available lotus leaf in every jump uniformly at random.

Since Alice and Bob have already being playing games for decades, so they want to know the probability that they jump to the nn - th lotus leaf with the same count of jumps.

输入描述

The first line contains an integer n(2n8000)n (2 \leq n \leq 8\,000), denoting the number of lotus leaf.

The second line contains n1n−1 integers a1,a2,,an1a_1, a_2, \ldots, a_{n-1} , where the ii - th integer ai(1aini)a_i (1 \leq a_i \leq n-i) indicates the range of lotus leaves that can be reached from the ii-th lotus leaf.

输出描述

Output a line containing a single integer, indicating the probability that Alive and Bob jump to nn-th lotus leaf with the same count of jumps, taken modulo 998244353998\,244\,353.

Formally speaking, let the result, which is a rational number, be xy\frac{x}{y} as an irreducible fraction, you need to output xy1mod998244353x \cdot y^{-1} \bmod{998\,244\,353} , where y1y^{-1} is a number such that yy11(mod998244353)y \cdot y^{-1} \equiv 1 \pmod{998\,244\,353}. You may safely assume that such y1y^{-1} always exists.

输入样例1:

5
1 1 1 1

输出样例1:

1

输入样例2:

5
4 3 2 1

输出样例2:

440198031

题意

nn 个点以及 22 个青蛙,22 个青蛙起始点均为 11号点,对于每个点 ii (1in1)(1\leq i \leq n-1) 都可等概率的跳跃至 (i,i+ai](i, i + a_i] 号点,求两青蛙跳跃相同的步数跳至 nn 号点的概论对 998244353998\,244\,353 取模.

思路

考虑从前往后递推 dp[i][j]dp[i][j] 意为跳跃 ii 步到达 jj 点的概率 一共 nn 个点最多跳跃 n1n-1

22 个青蛙花费相同步数到达 nn 号点的概论 两个青蛙都要到达即概论的平方 即 i=1n1dp[i][n]2\sum\limits_{i=1}^{n-1}dp[i][n]^2

显然从前往后递推转移方程为 dp[i+1][j+(1a[j])]=dp[i+1][j+(1 \sim a[j])]= dp[i+1][j+(1a[j])]+dp[i+1][j+(1 \sim a[j])] + dp[i][j]/a[j]dp[i][j]/a[j]

暴力转移时间复杂度是 O(n3)O(n^3) 的显然不行

观察转移方程可知每个点都是对其能跳跃到的区间做出相同的贡献 即区间加

然后对下一次跳跃的状态用前缀即可求值(注意每次转移都只与上次转移过来的值有关 故差分数组做完前缀后要清空)

这样的时间复杂度可以降到 O(n2)O(n^2)

注意逆元先线性求好 不然带个 loglogTLETLE

当然 高兴的话开个滚动数组维护也行 可以省点内存

Code

#include<bits/stdc++.h>
using namespace std;
#define __T int csT;scanf("%d",&csT);while(csT--)
#define endl '\n'
#define int long long
const int mod=998244353;
const double PI= acos(-1);
const double eps=1e-6;
const int N=2e5+7;

int n;
long long ans,sum;
long long dp[8003][8003],cf[8003];
long long a[8003],inv[8003];
void get_inv()
{
    inv[1]=1;
    for(int i=2;i<=n;i++)
    {
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    }
}//线性求逆元
inline void sol()
{
    scanf("%lld",&n);
    get_inv();
    for(int i=1;i<n;++i)scanf("%lld",&a[i]);
    dp[0][1]=1;
    for(int i=1;i<n;++i)
    {
        for(int j=i;j<n;++j)
        {
            cf[j+1]=(cf[j+1]+dp[i-1][j]*inv[a[j]]%mod)%mod;
            cf[j+a[j]+1]=(cf[j+a[j]+1]-dp[i-1][j]*inv[a[j]]%mod+mod)%mod;
        }
        sum=0;
        for(int j=1;j<=n;++j)
        {
            sum=(sum+cf[j])%mod;
            cf[j]=0;
            dp[i][j]=sum;
            //printf("%d %d %lld\n",i,j,dp[i][j]);
        }
    }
    ans=0;
    for(int i=1;i<n;++i)ans=(ans+dp[i][n]*dp[i][n]%mod)%mod;
    printf("%lld\n",ans);
}
signed main()
{
    //__T
    sol();
    return 0;
}
全部评论

相关推荐

点赞 评论 收藏
分享
评论
7
收藏
分享
牛客网
牛客企业服务