http://codeforces.com/contest/1342/problem/E
题意:
给n*n棋盘,要放n个棋。
每个棋的攻击范围为所在行和列。要求所有位置都至少被一个棋子攻击。要求有k对棋子两两对视。
解析:
假设k=0,那么就是 n ! n! n!。
否则 k ∈ [ 1 , n − 1 ] k\in[1,n-1] k∈[1,n−1],情况是n个棋子占据 n − k n-k n−k个行或者 n − k n-k n−k个列。
那么方案数是 2 ⋅ C ( n , n − k ) ⋅ F ( n , n − k ) 2\cdot C(n,n-k)\cdot F(n,n-k) 2⋅C(n,n−k)⋅F(n,n−k)。( F ( n , m ) F(n,m) F(n,m)表示将n个不同的球分到m个不同的盒子的方案数)
F ( n , m ) = m ! S 2 ( n , m ) F(n,m)=m!S_2(n,m) F(n,m)=m!S2(n,m),但是我们这里只需要求一个而已。
考虑容斥,至少 i i i个盒子为空的方案数为 C ( m , m − i ) ⋅ ( m − i ) n C(m,m-i)\cdot (m-i)^n C(m,m−i)⋅(m−i)n,对于这些容斥即可。
F ( n , m ) = ∑ i = 0 m ( − 1 ) i C ( m , m − i ) ⋅ ( m − i ) n F(n,m)=\sum_{i=0}^m(-1)^{i}C(m,m-i)\cdot (m-i)^n F(n,m)=∑i=0m(−1)iC(m,m−i)⋅(m−i)n
代码:
/*
* Author : Jk_Chen
* Date : 2020-04-29-10.30.11
*/
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<"> "<<x<<" ";test(args...);}
const LL mod=998244353 ;
const int maxn=2e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/
LL Pow(LL a,LL b,LL mod){
if(a>=mod)a%=mod;
LL res=1;
while(b>0){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
/*_________________________________________________________Pow*/
LL fac[maxn];
LL ifac[maxn];
LL C(LL n,LL m){return fac[n]*ifac[m]%mod*ifac[n-m]%mod; }
LL deal(LL n,LL m){
LL ans=0;
LL f=1;
rep(i,0,m){
ans+=f*C(m,m-i)*Pow(m-i,n,mod)%mod;
ans=(ans%mod+mod)%mod;
f=-f;
}
return ans;
}
int main(){
fac[0]=1;
rep(i,1,maxn-1)fac[i]=fac[i-1]*i%mod;
ifac[maxn-1]=Pow(fac[maxn-1],mod-2,mod);
per(i,maxn-2,0)ifac[i]=ifac[i+1]*(i+1)%mod;
LL n=rd,k=rd;
if(k>=n)return 0*printf("%d\n",0);
if(k==0)return 0*printf("%lld\n",fac[n]);
printf("%lld\n",2ll*C(n,n-k)*deal(n,n-k)%mod);
return 0;
}
/*_________________________________________________________end*/