• Wannafly挑战赛16 C-小球碰撞


    标签 : 数学 逆元


    题目描述

    一个弹球(可视为质点)被水平抛出,落地时发生完全弹性碰撞,设弹球第一次落地位置为x,则第i次落地位置为(2i-1)x.若弹球第一次落地的位置在区间[L,R]均匀随机分布,求弹球落在区间[L,R]内的总次数的数学期望值 
    可以证明答案为有理数,若答案表示为最简分数为a/b,则存在c使得bc mod 998244353 = 1 ,只需输出ac mod 998244353

    输入描述:

    第一行,一个整数n
    接下来n行,每行两个空格分隔的整数L,R
    (1<=n<=50000,1<=L<R<=10000000)

    输出描述:

    输出n行,每行一个整数,表示a*c mod 998244353

    示例

    输入

    3
    3 4
    3 5
    1 5

    输出

    1
    1
    166374060

    分析

    1. 首先考虑会落在区间内恰好k次的初始下落位置的集合。显然,当满足((2k-1)x leq R)((2k+1)x > R)
    2. 化简1中式子可以得到(x in( frac{R}{2k+1},frac{R}{2k-1}]),所以应有(x in( max(L,frac{R}{2k+1}),max(L,frac{R}{2k-1})])
    3. 所以下落k次的概率为(f(k)= frac{max(L,frac{R}{2k-1}) - max(L,frac{R}{2k+1})}{R-L})
    4. 所求期望为 $$E(k)=sum_{k=1}^{+infty}kf(k)$$

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const ll MOD=998244353;
    const int maxn=1e7+50;
    ll inv[maxn],sum[maxn];
    void init()
    {
        inv[1]=sum[1]=1;
        for(int i = 2; i < maxn; ++i) inv[i]=(-MOD/i+MOD)*inv[MOD%i]%MOD,sum[i]=(sum[i-2]+inv[i])%MOD;
    }
    int main()
    {
        init();
        int q;
        scanf("%d", &q);
        while(q--){
            ll l,r;
            scanf("%lld%lld" ,&l,&r);
            ll e=(r/l+1)/2;
            ll ans=sum[2*e-1]-l*inv[r]%MOD*e%MOD;
            ans%=MOD;
            ans=ans*r%MOD*inv[r-l]%MOD;
            ans=(ans%MOD+MOD)%MOD;
            printf("%lld
    ", ans);
        }
    }
    
  • 相关阅读:
    双重标准,我该怎么解决
    今天突然点开一个网页
    反省
    (无)
    (无)
    GetModuleHandleW 分析
    关于逆向360相关的一点感想
    OpenGL的编译和使用
    360 补天平台,也没个什么人啊。。。
    openssl编译方法
  • 原文地址:https://www.cnblogs.com/sciorz/p/9093593.html
Copyright © 2020-2023  润新知