CF Global Round 28 题解合集

here.

D

考虑水平 \(\le a_1\) 的选手不可能排在 1 号前面,所以把他们豆沙了。

现在只需要考虑怎样组题了。我们定义 \(c_i\) 表示第 \(i\) 题能够有几个人会,特别地,如果 \(b_i \le a_1\),那么 \(c_i=0\)\(c\) 可以排序后用双指针求出。

于是我们组一场比赛,用第 \([1,k]\) 道题,1 号的排名就是 \(\max_{i=1}^{k} c_i\)

贪心地考虑,将 \(c\) 升序排序,每场比赛选择一段连续的 \(c\),一定是最优的。

复杂度 \(O(n \log n)\),log 来源于调和级数。

E

发现存在合法方案的一个必要条件是,\(n(2n+m-1) \ge 2nm\),也就是 \(2n-1\ge m\)

我们考虑构造使得对于 \(2n-1\ge m\) 的所有情况,必然存在合法方案。

也就是说,我们需要对于每一个颜色,构造一棵原图的生成树,并且边集两两不交。

我们考虑这样一种构造方案:

【TBD】

按题意模拟即可。

F

看到区间对 \(\min_{i=l}^{r} b_i\) 操作优先考虑笛卡尔树。

又注意到,答案上界为 \(O(\log v)\)

考虑在笛卡尔树上进行 DP,设 \(f_{x,i}\) 表示考虑 \(x\) 的子树区间内,操作了 \(i\) 次,最小化最大值。

转移考虑一个树上背包,也就是:

\[f_{x,i}\leftarrow \max(f_{y,j},f_{x,i-j}) \]

然后也可以在当前位置操作:

\[f_{x,i}\leftarrow\min(f_{x,i},\lceil\frac{f_{x,i-1}}{b_x}\rceil) \]

复杂度 \(O(n \log^2 v)\)

G

注意到,矩阵合法,当且仅当存在一个位置,满足它是行的最小值,同时也是列的最大值。

注意到,如果两个位置 \((a,b),(c,d)\) 都满足上面的性质,那么 \((a,c),(b,d)\) 也满足条件。

于是考虑二项式反演,钦定关键点纵坐标和横坐标集合的大小,以及关键点的点权,剩下位置任意选择,有:

\[\sum_{x=1}^{n}\sum_{y=1}^{m}\sum_{c=1}^{v} (-1)^{x+y}\binom{n}{x}\binom{m}{y}c^{x(m-y)}(v-c+1)^{y(n-x)}v^{(n-x)(m-y)} \]

这个东西看起来没戏,所以我们尝试把 \(y\) 的枚举用二项式定理干掉:

\[\sum_{x=1}^{n}(-1)^x\binom{n}{x}\sum_{c=1}^{v}\sum_{y=1}^{m}(-1)^y\binom{m}{y}((v-c+1)^{n-x})^{y}(c^xv^{n-x})^{m-y} \]

\[\sum_{x=1}^{n}(-1)^x\binom{n}{x}\sum_{c=1}^{v}(c^xv^{n-x}-(v-c+1)^{n-x})^m-(c^xv^{n-x})^m \]

复杂度为 \(O(nv\log m)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353,maxn=1e6;
int t,n,m,v,sum,ans,fac[1000005];
int binpow(int a,int b){
    if(b==0) return 1;
    int res=binpow(a,b/2);
    if(b&1) return res*res%mod*a%mod;
    else return res*res%mod;
}
int C(int n,int m){
    if(n<m) return 0;
    return fac[n]*binpow(fac[m],mod-2)%mod*binpow(fac[n-m],mod-2)%mod;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    fac[0]=1;
    for(int i=1;i<=maxn;i++){
        fac[i]=fac[i-1]*i%mod;
    }
    cin>>t;
    while(t--){
        cin>>n>>m>>v;
        ans=0;
        for(int x=1;x<=n;x++){
            int sum=0;
            for(int c=1;c<=v;c++){
                sum=(sum+binpow((binpow(c,x)*binpow(v,n-x)%mod-binpow(v-c+1,n-x)+mod)%mod,m)-binpow(binpow(c,x)*binpow(v,n-x)%mod,m)+mod)%mod;
            }
            sum=sum*C(n,x)%mod;
            if(x&1) ans=(ans-sum+mod)%mod;
            else ans=(ans+sum)%mod;
        }
        cout<<ans<<'\n';
    }
    return 0;
}
posted @ 2025-04-13 16:53  _Kenma  阅读(8)  评论(0)    收藏  举报