LuoguP4931情侣?给我烧了

情侣?给我烧了

组合题。。。要推公式:

 

首先考虑和谐的k对情侣:

 从n对中选出k对:C[n][k]。

从n排座位中选出k排座位:C[n][k]。

情侣的排列方式:k!。

一对情侣可以互换位置,每队可以选择换或不换:2k

综上,这一部分的贡献为:C[n][k]2*k!*2k

 

接下来考虑n-k对情侣不坐在一起的情况:

不妨设f[x]表示x对情侣不坐在一起的方案数。

首先从2*x个人中选出一个人坐下:2*x。

选一个人和他坐一排且不是他的情侣:2*x-2。

所以,选出两个非情侣的人坐一排方案数:(2*x)*(2*x-2)。

那么接下来有两种情况:

① 这两个人的情侣坐一起:2*(x-1)*f[x-2]。

② 这两个人的情侣不坐一起,那么这两人可视为新的一对情侣:f[x-1]。

综上我们发现f[x]的递推式:f[x]=(2*x)*(2*x-2)*(2*(x-1)*f[x-2]+f[x-1])。

 

所以最后的ans=C[n][k]2*k!*2k*f[n-k]。

提前预处理:阶乘,阶乘逆元,2的幂,f[]。

 

#include<bits/stdc++.h>
#define RG register
#define IL inline
#define DB double 
#define int long long
using namespace std;

IL int gi() {
    RG int x=0,w=0; char ch=0;
    while (ch<'0'||ch>'9') {if (ch=='-') w=1;ch=getchar();}
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return w?-x:x;
}

const int N=5e6;
const int mod=998244353;

int n,k,C,G[N+2],pw[N+2],fc[N+2],fcn[N+2];

IL int power(int x,int P) {
    RG int ans=1;
    for (;P;P>>=1,x=x*x%mod)
        if (P&1) ans=ans*x%mod;
    return ans;
}

IL void For_pre() {
    RG int i;
    for (i=1,fc[0]=1,fcn[0]=1;i<=N;++i)
        fc[i]=fc[i-1]*i%mod;
    for (i=1,pw[0]=1;i<=N;++i) 
        pw[i]=(pw[i-1]+pw[i-1])%mod;
    G[0]=1,G[1]=0,G[2]=16;
    for (i=3;i<=N;++i)
        G[i]=(i+i)*(i+i-2)%mod*(G[i-1]+(i+i-2)*G[i-2]%mod)%mod;
}

signed main ()
{
    RG int T=gi();
    For_pre();
    while (T--) {
        n=gi(),k=gi();
        if (!fcn[k]) fcn[k]=power(fc[k],mod-2);
        if (!fcn[n-k]) fcn[n-k]=power(fc[n-k],mod-2);
        C=fc[n]*fcn[k]%mod*fcn[n-k]%mod;
        printf("%lld\n",C*C%mod*fc[k]%mod*pw[k]%mod*G[n-k]%mod);
    }
    return 0;
}
BY BHLLX

 

posted @ 2019-02-13 09:27  薄荷凉了夏  阅读(177)  评论(0编辑  收藏  举报