[CF1525E]Assimilation IV

Posted Arextre

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1525E]Assimilation IV相关的知识,希望对你有一定的参考价值。

壹、题目描述 ¶

传送门 to CF.

贰、题解 ¶

显然,这是要单独考虑每个城市对于答案的贡献。

对于每个城市,我们可以考虑它被覆盖的情况有多少种,但是尝试之后不难发现,这样计算太复杂了 —— 一个城市可以只被一个点覆盖,也可能被两个,三个......

考虑容斥?容斥什么?怎么容斥?时间复杂度再怎么也要个 \\(2^n\\) 吧?复杂度 \\(\\mathcal O(m2^n)\\)?Soshite?

显然,这个思路不可取,但是我们总不可能离开 “方案” 吧?但是我们可以考虑正难则反

对于一个城市,总的方案数有 \\(n!\\) 种,我们只需要计算出不能覆盖它的点选择情况就好了。

显然,在第 \\(i\\) 次选择点的时候,选择点的距离必须要严格大于 \\(n-i+1\\),所以,我们记 \\(cnt(i,j)\\) 表示到达城市 \\(i\\) 的点中,距离严格大于 \\(j\\) 的有多少。

那么对于一个点,它不被覆盖的方案数即

\\[\\prod_{i=1}^{n}(cnt(i,n-j+1)-j+1) \\]

为什么后面还要 \\(-j+1\\)?因为在前面 \\([1,i-1]\\) 次选择种,已经选了一些点,而我们不能重复选择这些已经被选择的点,所以得减去。

但是注意特殊情况,当出现 \\(cnt(i,n-j+1)-j+1\\le 0\\) 时,说明这个点无论如何都会被选择,直接让方案数为 \\(0\\) 即可。

叁、参考代码 ¶

const int maxn=20;
const int maxm=5e4;
const int mod=998244353;

inline int qkpow(int a, int n){
    int ret=1;
    for(; n; n>>=1, a=1ll*a*a%mod)
        if(n&1) ret=1ll*ret*a%mod;
    return ret;
}

int d[maxn+5][maxm+5];
int n, m;
int cnt[maxm+5][maxn+5];

inline void input(){
    n=readin(1), m=readin(1);
    rep(i, 1, n) rep(j, 1, m)
        d[i][j]=readin(1);
}

signed main(){
    input();
    rep(i, 1, m) rep(j, 1, n) rep(k, 1, n) if(d[k][i]>j)
        ++cnt[i][j];
    int ans=0, fac=1;
    rep(i, 1, n) fac=1ll*fac*i%mod;
    rep(i, 1, m){
        int cur=1;
        rep(j, 1, n){
            if(cnt[i][n-j+1]-j+1<=0){ cur=0; break; }
            cur=1ll*cur*(cnt[i][n-j+1]-j+1)%mod;
        }
        ans=(0ll+ans+fac+mod-cur)%mod;
    }
    ans=1ll*ans*qkpow(fac, mod-2)%mod;
    printf("%d\\n", ans);
    return 0;
}

肆、用到 の Trick ¶

正着算方案时,如果遇到困难,何不试试正难则反?

以上是关于[CF1525E]Assimilation IV的主要内容,如果未能解决你的问题,请参考以下文章

普林斯顿数学指南(第二卷)

题解 SP2713 GSS4 - Can you answer these queries IV

寒假代更新计划

每日cf计划

模数循环节——cf547A

CF739E Gosha is hunting WQS二分 + 期望