zoukankan      html  css  js  c++  java
  • [CF1342E] Placing Rooks

    前言

    数学就要多练练

    题目

    洛谷

    CF

    讲解

    首先易证当(n le k)时无解,(k=0)时答案为((n-1)!)

    此时由于行和列是等价的,所以我们先只考虑对于每行只放一个车,最后将答案乘二即可

    考虑放下一个车之后,如果当前列没有车,则对攻击数量不会有贡献,我们希望有(k)对车可以和互相攻击,则我们要放(n-k)

    对于(n)行,每行有(n-k)个位置可以放,则答案为(C_n^{n-k}*(n-k)^n)

    吗?

    很明显这样是错的,这样的统计会将放(le n-k)列的方案全部算进去,但我们需要的是恰好放(n-k)列的方案

    典型的容斥,设(n-k)列中有(i)列一定为空,容斥式子为:

    [S=sum_{i=0}^{n-k}(-1)^i*C_{n-k}^{i}*(n-k-i)^n ]

    最终答案即为:

    [C_n^{n-k}*S*2 ]

    代码

    int qpow(int x,int y)
    {
    	int ret = 1;
    	while(y){if(y & 1) ret = 1ll * ret * x % MOD;x = 1ll * x * x % MOD;y >>= 1;}
    	return ret;
    }
    int fac[MAXN],ifac[MAXN];
    void pre(int x)
    {
    	fac[0] = 1;
    	for(int i = 1;i <= x;++ i) fac[i] = 1ll * fac[i-1] * i % MOD;
    	ifac[x] = qpow(fac[x],MOD-2);
    	for(int i = x-1;i >= 0;-- i) ifac[i] = 1ll * ifac[i+1] * (i+1) % MOD;
    }
    int C(int x,int y)
    {
    	if(x < y) return 0;
    	return 1ll * fac[x] * ifac[y] % MOD * ifac[x-y] % MOD;
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read(); k = Read();
    	if(k >= n){Put(0);return 0;}
    	pre(200000);
    	if(!k){Put(fac[n]);return 0;}
    	for(int i = 0;i <= n-k;++ i)
    	{
    		LL f = (i&1) ? -1 : 1;
    		ans = (ans + f * C(n-k,i) * qpow(n-k-i,n)) % MOD;
    	}
    	ans = ans * C(n,n-k) * 2 % MOD;
    	Put((ans + MOD) % MOD);
    	return 0;
    }
    
  • 相关阅读:
    第11组 Beta冲刺(1/5)
    第11组 Alpha事后诸葛亮
    第11组 Alpha冲刺(6/6)
    第11组 Alpha冲刺(5/6)
    软工实践个人总结
    第11组 Beta版本演示
    第11组 Beta冲刺(5/5)
    第11组 Beta冲刺(4/5)
    第11组 Beta冲刺(3/5)
    第11组 Beta冲刺(2/5)
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/13636941.html
Copyright © 2011-2022 走看看