正解:数论+$dp$

解题报告:

传送门

首先关于前面k对情侣的很简单,就是$C(n,k)\cdot C(n,k)\cdot A(k,k)\cdot 2^k$.随便解释下,就是选座位*选情侣*情侣选座位*情侣之间换左右位置

然后难点大概在于后面的$(n-k)$对不能在一起的怎么求方案数

就考虑,$dp$,设$f[i]$表示$i$对情侣的情况

然后随便选一排,显然选人有$2\cdot i\cdot (2\cdot i-2)$

那对他们的情侣,有两种可能

一种是他们的情侣就坐一块儿了,于是就是$(i-2)\cdot 2\cdot f_{i-1}$(坐哪排,换左右位置,剩下$i-2$排的方案

另一种就是不坐一块呗,那我们就要强制让他们不做一块

  思考不坐一起这个阶段情侣的定义,不就是不能坐一起的人嘛

  于是这一对儿就成了一对新情侣($hhh$听着有点鬼畜$x$

  所以就是$f_{i-1}$

综上!这题就做完了!

总结一下式子:$C(n,k)\cdot C(n,k)\cdot A(k,k)\cdot 2^k\cdot f_{n-k},f_i=2\cdot i\cdot (i-1)\cdot (2\cdot (i-1)\cdot f_{i-2}+f_{i-1})$

$over!$

(对了!神仙$tr$还港了种,神仙才能用的方法,,,就暴力,求导微分搞下就搞完了,,,$QwQ$

洛谷P4931 情侣给我烧了! 数论+$dp$洛谷P4931 情侣给我烧了! 数论+$dp$
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rg register
#define rp(i,x,y) for(rg ll i=x;i<=y;++i)
#define my(i,x,y) for(rg ll i=x;i>=y;--i)

const ll N=5000000+5,mod=998244353;
ll T,mx,fac[N]={1},poww[N]={1},inv[N],f[N]={1,0},n[N],k[N];

inline ll read()
{
    rg char ch=getchar();rg ll x=0;rg bool y=1;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=getchar();
    if(ch=='-')ch=getchar(),y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar();
    return y?x:-x;
}
inline ll power(ll x,ll y){ll as=1;while(y){if(y&1)as=(ll)x*as%mod;y>>=1;x=(ll)x*x%mod;}return as;}
inline ll dec(ll a,ll b){a-=b;return a<0?a+mod:a;}
inline ll inc(ll a,ll b){a+=b;return a>=mod?a-mod:a;}
inline ll C(ll n,ll m){return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;}
inline ll A(ll n,ll m){return (ll)fac[n]*inv[n-m]%mod;}

int main()
{
    T=read();rp(i,1,T)mx=max(mx,n[i]=read()),k[i]=read();++mx;
    rp(i,1,mx)poww[i]=inc(poww[i-1],poww[i-1])%mod,fac[i]=(ll)fac[i-1]*i%mod;
    inv[mx]=power(fac[mx],mod-2);my(i,mx,1)inv[i-1]=(ll)inv[i]*i%mod;
    rp(i,2,mx)f[i]=(ll)inc(2*(i-1)*f[i-2]%mod,f[i-1])*4%mod*i%mod*(i-1)%mod;
    rp(i,1,T)printf("%lld\n",(ll)A(n[i],k[i])*C(n[i],k[i])%mod*poww[k[i]]%mod*f[n[i]-k[i]]%mod);
    return 0;
}
放下代码QAQ

然后这题有个双倍经验,和这题差不多的$QwQ$方法什么的都一样代码也不用变多少

我就放下代码就溜了$QAQ$

洛谷P4931 情侣给我烧了! 数论+$dp$洛谷P4931 情侣给我烧了! 数论+$dp$
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rg register
#define rp(i,x,y) for(rg ll i=x;i<=y;++i)
#define my(i,x,y) for(rg ll i=x;i>=y;--i)

const ll N=5000000+5,mod=998244353;
ll T,mx,fac[N]={1},poww[N]={1},inv[N],f[N]={1,0},n[N];

inline ll read()
{
    rg char ch=getchar();rg ll x=0;rg bool y=1;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=getchar();
    if(ch=='-')ch=getchar(),y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar();
    return y?x:-x;
}
inline ll power(ll x,ll y){ll as=1;while(y){if(y&1)as=(ll)x*as%mod;y>>=1;x=(ll)x*x%mod;}return as;}
inline ll dec(ll a,ll b){a-=b;return a<0?a+mod:a;}
inline ll inc(ll a,ll b){a+=b;return a>=mod?a-mod:a;}
inline ll C(ll n,ll m){return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;}
inline ll A(ll n,ll m){return (ll)fac[n]*inv[n-m]%mod;}

int main()
{
    T=read();rp(i,1,T)mx=max(mx,n[i]=read());++mx;
    rp(i,1,mx)poww[i]=inc(poww[i-1],poww[i-1])%mod,fac[i]=(ll)fac[i-1]*i%mod;
    inv[mx]=power(fac[mx],mod-2);my(i,mx,1)inv[i-1]=(ll)inv[i]*i%mod;
    rp(i,2,mx)f[i]=(ll)inc(2*(i-1)*f[i-2]%mod,f[i-1])*4%mod*i%mod*(i-1)%mod;
    rp(i,1,T)
        rp(j,0,n[i])printf("%lld\n",(ll)A(n[i],j)*C(n[i],j)%mod*poww[j]%mod*f[n[i]-j]%mod);
    return 0;
}
View Code

 

相关文章: