[luogu4931]情侣?给我烧了!


题解

\(i\)对情侣全都不和谐那里推不出来只好写了一个暴力容斥然后大力卡常卡过去了==
容斥太过暴力,还是说正解吧
可以考虑直接计算\(n\)对情侣有\(k\)对和谐的方案数
\(g[i]\)表示\(i\)对情侣\(2*i\)个座位,这\(i\)对情侣全都不和谐的方案数
那么答案显然就是\(C(n,k)*C(n,k)*fac[k]*2^k*g[n-k]\)
那么主要问题就是这个\(g[]\)怎么求
我们可以考虑像错排那样来推一下这个东西:
考虑有\(n\)对情侣:首先随便选一个坐在第一排的第一个位置,然后再选不是ta的情侣的坐在第一排的第二个位置,方案数是\((n*2)*(n*2-2)\)
那么考虑坐第一排的那两对的情侣,如果那两个也坐在同一排,方案数就是\((n-1)*g[n-2]\)
如果那两人不坐在同一排,那么可以把他们当做一对情侣,那么方案数就是\(g[n-1]\)
所以\(g[n]=(n*2)*(n*2-2)(g[n-1] +(n-1)*g[n-2])\)

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int M = 5000005 ;
const int mod = 998244353 ;
using namespace std ;

inline int read() {
    char c = getchar() ; int x = 0 , w = 1 ;
    while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
    while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
    return x*w ;
}

int n , k , f[M] , fac[M] , inv[M] , finv[M] , pw2[M] ;
inline int C(int n , int m) {
    return 1LL * fac[n] * finv[m] % mod * finv[n - m] % mod ;
}
inline int Calc(int n) {
    return (1LL * n * 2 * (n * 2 - 2) % mod * (n - 1) * 2 % mod * f[n - 2] + 1LL * n * 2 * (n * 2 - 2) % mod * f[n - 1] % mod ) % mod ;
}
int main() {
    fac[0] = 1 ; 
    for(int i = 1 ; i <= 5000000 ; i ++) fac[i] = 1LL * fac[i - 1] * i % mod ;
    inv[1] = 1 ;
    for(int i = 2 ; i <= 5000000 ; i ++) inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod ;
    finv[0] = 1 ;
    for(int i = 1 ; i <= 5000000 ; i ++) finv[i] = 1LL * finv[i - 1] * inv[i] % mod ;
    pw2[0] = 1 ;
    for(int i = 1 ; i <= 5000000 ; i ++) pw2[i] = pw2[i - 1] * 2 % mod ;
    f[0] = 1 ; f[1] = 0 ;
    for(int i = 2 ; i <= 5000000 ; i ++) f[i] = Calc(i) ;
 	int Case = read() ;
 	while(Case --) {
 		n = read() ; k = read() ;
 		printf("%d\n", (1LL * C(n , k) * C(n , k) % mod * fac[k] % mod * pw2[k] % mod * f[n - k] % mod + mod) % mod) ;
    }
    return 0 ;
}
posted @ 2019-03-13 22:01  beretty  阅读(133)  评论(0编辑  收藏  举报