• Luogu3600 随机数生成器


    题面

    传送门

    Sol

    $sto $ (fdf)
    $sto $ (fateice)

    显然,如果一个区间包含了另一个区间,那么它的最小值不会有贡献,直接去掉

    考虑枚举最大值(k)
    求出所有区间满足最小值小于等于(k)的概率,设为(P[k])
    那么(k)的贡献就是((P[k]-P[k-1])*k),相当于差分了一下

    然后考虑算出(P[k])
    (f[i])表示到(i)时,所有右端点都小于等于(i)的区间都满足要求的概率
    枚举右端点在(i)的所有左端点(j)
    枚举在哪里弄一个小于等于(k)

    [f[i]=sum_{l=j}^{i}f[l-1]*(frac{k}{x})*(1-frac{k}{x})^{i-l} ]

    枚举的这个点之前的随便选,而后面的只能选大于(k)
    这样才能做到不重复计算,因为如果后面的也随便选,那么会和之前的有交集
    然后这是(n^3x)的,居然过了
    (n,x<=2000)

    把上面的转移式拆一下,把(f[l-1]*(1-frac{k}{x})^{-l})做个前缀和就好了
    特别注意如果(i=l)并且(k=x)时,((1-frac{k}{x})^{i-l})要当成(1)
    那么特判一下就好了

    (fdf) $ orz( )fateice$ $ orz$

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(2005);
    const int Zsy(666623333);
    
    IL int Input(){
        RG int x = 0, z = 1; RG char c = getchar();
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
    
    int n, x, Q, tp, f[_], g[_], ans, first[_], nxt[_], inv;
    struct Query{
        int l, r;
    
        IL int operator <(RG Query B) const{
            return l != B.l ? l < B.l : r < B.r;
        }
    } tmp[_], q[_];
    
    IL int Pow(RG ll x, RG ll y){
        RG ll ret = 1;
        for(; y; y >>= 1, x = x * x % Zsy)
            if(y & 1) ret = ret * x % Zsy;
        return ret;
    }
    
    IL void Upd(RG int &x, RG int y){
        x += y;
        if(x >= Zsy) x -= Zsy;
    }
    
    IL int Sum(RG int l, RG int r){
    	return (g[r] - (l < 0 ? 0 : g[l]) + Zsy) % Zsy;
    }
    
    IL int Calc(RG int v){
        RG int p1 = 1LL * inv * v % Zsy, p2 = (1 + Zsy - p1) % Zsy, p3 = Pow(p2, Zsy - 2);
        Fill(g, 0), Fill(f, 0), g[0] = p3, f[0] = 1;
        for(RG int i = 1; i <= n; ++i){
            for(RG int p = first[i]; p; p = nxt[p]){
    			if(i > q[p].l) Upd(f[i], 1LL * Sum(q[p].l - 2, i - 2) * p1 % Zsy * Pow(p2, i) % Zsy);
    			Upd(f[i], 1LL * f[i - 1] * p1 % Zsy);
    		}
            if(!first[i]) f[i] = f[i - 1];
    		g[i] = g[i - 1], Upd(g[i], 1LL * f[i] * Pow(p3, i + 1) % Zsy);
        }
        return f[n];
    }
    
    int main(RG int argc, RG char *argv[]){
        n = Input(), x = Input(), tp = Input(), inv = Pow(x, Zsy - 2);
        for(RG int i = 1; i <= tp; ++i) tmp[i] = (Query){Input(), Input()};
        sort(tmp + 1, tmp + tp + 1);
        for(RG int i = 1; i <= tp; ++i){
            while(q[Q].r >= tmp[i].r) --Q;
            if(tmp[i].l > q[Q].l) q[++Q] = tmp[i];
        }
        for(RG int i = 1; i <= Q; ++i) nxt[i] = first[q[i].r], first[q[i].r] = i;
        for(RG int i = 1, lst = 0; i <= x; ++i){
            RG int now = Calc(i);
            ans = (ans + 1LL * i * ((now - lst + Zsy) % Zsy) % Zsy) % Zsy;
            lst = now;
        }
        printf("%d
    ", ans);
        return 0;
    }
    
    
  • 相关阅读:
    浅谈 facebook .net sdk 应用
    数据库中各种字符串的截取函数
    初、中、高级测试工程师面试题汇总(附答案)
    包管理器 scoop
    ModuleNotFoundError: No module named 'pymouse'解决办法
    Python 正则表达式(分组)
    7个Python实战项目代码,让你分分钟晋级大神!
    经典SQL查询题目
    linux中软件的安装和卸载方法
    测试常用工具
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8665132.html
Copyright © 2020-2023  润新知