zoukankan      html  css  js  c++  java
  • Wannafly Winter Camp 2020 Day 6D 递增递增

    给定两个常为 (n) 的序列 (l_i,r_i),问夹在它们之间 ( (forall i, l_i leq a_i leq r_i) ) 的不降序列的元素总和。

    Solution

    先搞一波离散化,把

    (f[i][j]) 表示处理完了 (a[1dots i]),且 (a[i]) 在第 (j) 个区间内的总和, (g[i][j]) 为方案数

    考虑运用分段的思想,枚举下一段的结束点 (p),以及下一段所在区间 (k),就可以暴力转移到 (f[p][k])

    [Af[i][j] + Bg[i][j] o f[p][k] \ Ag[i][j] o g[p][k] ]

    其中 (A) 是方案数, (B) 是总和,运用插板法与期望的线性性质得

    [t=p-i,quad A=C_{R_k-L_k+t}^t,quad B=frac{t(L_k+R_k)}{2}cdot C_{R-L+t}^t ]

    组合数如果每个都暴力计算复杂度是 (O(tlog V)) 的。显然 (C_{R-L+t}^t=frac{(R-L+t)!}{(R-L)!t!}),于是 (C_{R-L+t}^t=C_{R-L+t-1}^{t-1} cdot frac{R-L+t}{t})

    但是考虑到 (R_k-L_k) 之和 (k) 相关,所以我们需要用的组合数只有 (O(n^2)) 个,于是花费 (O(n^2 log V)) 时间暴力预处理 (c[k][t]=C_{R_k-L_k+t}^t) 即可。

    Warning: 运算过程会爆 long long

    #include <bits/stdc++.h>
    using namespace std;
    #define int __int128
    const bool dbg = 0;
    const int N = 105;
    const int mod = 998244353;
    const int r2 = 499122177;
    int f[N][N],g[N][N],c[N][N],n,L[N],R[N],l[N],r[N],pos[N],ind;
    map<int,int> mp;
    int qpow(int p,int q) {return ((q&1)?p:1) * (q?qpow(p*p%mod,q/2):1) % mod;}
    int inv(int p) {return qpow(p,mod-2);}
    void read(int &x) {
        long long a;
        cin>>a;
        x=a;
    }
    void write(int x) {
        cout<<(long long)x;
    }
    signed main() {
        read(n);
        for(int i=1;i<=n;i++) read(l[i]), mp[l[i]]++;
        for(int i=1;i<=n;i++) read(r[i]), r[i]++, mp[r[i]]++;
        for(auto i=mp.begin();i!=mp.end();i++) i->second=++ind, pos[ind]=i->first;
        for(int i=1;i<ind;i++) L[i]=pos[i], R[i]=pos[i+1];
        for(int i=1;i<=n;i++) l[i]=lower_bound(L+1,L+ind,l[i])-L, r[i]=lower_bound(R+1,R+ind,r[i])-R;
        for(int i=1;i<ind;i++) R[i]--;
        for(int i=1;i<ind;i++) {
            c[i][0]=1;
            for(int j=1;j<=n;j++) c[i][j]=c[i][j-1]*(((R[i]-L[i]+j)%mod+mod)%mod)%mod*inv(j)%mod;
        }
        g[0][0]=1;
        for(int i=0;i<=n;i++) {
            for(int j=0;j<ind;j++) if(((i==0)^(j==0))==0) {
                int lb=0,rb=ind;
                for(int p=i+1;p<=n;p++) {
                    lb=max(lb,l[p]);
                    rb=min(rb,r[p]);
                    for(int k=j+1;k<ind;k++) {
                        if(lb<=k && k<=rb) {
                            f[p][k] += c[k][p-i]*f[i][j]%mod
                                + (p-i)*(L[k]+R[k])%mod*r2%mod*c[k][p-i]%mod*g[i][j]%mod;
                            f[p][k] %= mod;
                            g[p][k] += c[k][p-i]*g[i][j]%mod;
                            g[p][k] %= mod;
                        }
                    }
                }
            }
        }
        int ans=0;
        for(int i=1;i<ind;i++) ans+=f[n][i], ans%=mod;
        write(ans);
    }
    
    
  • 相关阅读:
    Spring入门之通过注解 处理 数据库事务
    Spring 入门之-dao使用jdbcTemplate(注入过程)
    spring入门之JdbcTemplate 操作crud
    npm 包 升降版本
    vue-cli初始化一个项目
    <meta http-equiv="refresh" content="0; url=">
    vue-router的两种模式的区别
    Webstorm 的 Tab 键怎样调整缩进值? 调节成缩进成2个空格或者4个空格
    去抖函数 节流函数
    创建一个vue项目,vue-cli,webpack
  • 原文地址:https://www.cnblogs.com/mollnn/p/12363573.html
Copyright © 2011-2022 走看看