[CF1525E]Assimilation IV
Posted Arextre
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1525E]Assimilation IV相关的知识,希望对你有一定的参考价值。
壹、题目描述 ¶
贰、题解 ¶
显然,这是要单独考虑每个城市对于答案的贡献。
对于每个城市,我们可以考虑它被覆盖的情况有多少种,但是尝试之后不难发现,这样计算太复杂了 —— 一个城市可以只被一个点覆盖,也可能被两个,三个......
考虑容斥?容斥什么?怎么容斥?时间复杂度再怎么也要个 \\(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的主要内容,如果未能解决你的问题,请参考以下文章