1. 程式人生 > >LuoguP4931情侶?給我燒了

LuoguP4931情侶?給我燒了

def oid .org 推公式 bit ons 一個人 tps while

情侶?給我燒了

組合題。。。要推公式:

首先考慮和諧的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

LuoguP4931情侶?給我燒了