zoukankan      html  css  js  c++  java
  • 题解-洛谷4921&4931 情侣?给我烧了!(加不加强无所谓版)

    Problem

    简单版 & 加强版

    题目概要(其实题面写得很清楚,这里搬运一下):

    (n) 对情侣排座位,恰有 (n) 排座位,每排 (2) 个座位,在一个就座方案中所有人会将将座位坐满(共有 ((2n)!) 种不同的就坐方案。)

    求出共有多少种不同的就坐方案满足恰好有 (k) 对情侣坐在一排

    • 简单版:给出 (Tleq 10^3) 组数据,每组数据给出 (nleq 10^3),对于每个 (kin [0,n]) 输出
    • 加强版:给出 (Tleq 2 imes 10^5) 组数据,每组数据给出 (nleq 5 imes 10^6),对于给出的 (kin[0,n]) 输出

    每组询问间 (n,k) 不保证相同

    Complains

    这题目名……让很久没见妹子的我很是心酸啊……

    写完简单版发现可以直接过加强版,于是就把这两题写在一起了啦 这题为啥是黑题啊

    本来想容斥搞事的,结果推出来始终过不了样例

    但估计有简单版和加强版之分,估计简单版是容斥,求dalao指教怎么容斥啊

    Solution

    然后就尝试着直接做,那对于恰有 (k) 对情侣的就坐方案,首先要选出 (k) 对情侣 (inom nk),然后要给他们安排对应的位置 (P_n^k),再算上一排座位间怎么坐都是一样的 (2^n),最后要限制其他 (n-k) 对情侣都不在一排

    最后一个问题明显是错排,错排的式子是 (D_n=(n-1)(D_{n-1}+D_{n-2})),是由增量法得到的

    在这题里,情侣之间不好考虑,然后错排中每加入两个人,和传统的错排一样,只是两个人要选择一个调换到前边去,所以要乘 (2),所以得到递推式为 (d_i=2(i-1)(d_{i-1}+d_{i-2})),最后要乘上加入的顺序 (i!)

    所以最后的答案为

    [Ans=C_n^kcdot P_n^kcdot 2^ncdot (n-k)!cdot d_{n-k} ]

    所以这种 (O(n)) 预处理 (O(1)) 查询的做法两道题都能过

    Code

    简单版

    #include <cstdio>
    typedef long long ll;
    
    const int N=1013,p=998244353;
    int fac[N],inv[N],g[N],f[N],pw2[N];
    int n;
    
    inline int C(int nn,int mm){return (ll)fac[nn]*inv[mm]%p*inv[nn-mm]%p;}
    inline int P(int nn,int mm){return (ll)fac[nn]*inv[nn-mm]%p;}
    
    inline int qpow(int A,int B){
    	int res(1);while(B){
    		if(B&1)res=(ll)res*A%p;
    		A=(ll)A*A%p,B>>=1;
    	}return res;
    }
    
    int main(){
    	pw2[1]=2;inv[0]=g[0]=1;
    	fac[0]=fac[1]=pw2[0]=1;
    	for(int i=2;i<N;++i){
    		fac[i]=(ll)fac[i-1]*i%p;
    		pw2[i]=2ll*pw2[i-1]%p;
    		g[i]=2ll*(i-1)*(g[i-1]+g[i-2])%p;
    	}
    	inv[N-1]=qpow(fac[N-1],p-2);
    	for(int i=N-2;i;--i)inv[i]=(ll)inv[i+1]*(i+1)%p;
    	
    	int T,n;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d",&n);
    		for(int i=0;i<=n;++i)
    			printf("%lld
    ",(ll)C(n,i)*P(n,i)%p *pw2[n]%p *fac[n-i]%p *g[n-i]%p);
    	}
    }
    

    加强版

    #include <bits/stdc++.h>
    typedef long long ll;
    
    inline void read(int&x){
    	char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
    	while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
    }
    
    const int N=5001001,p=998244353;
    int fac[N],inv[N],g[N],f[N],pw2[N];
    int n;
    
    inline int C(int nn,int mm){return (ll)fac[nn]*inv[mm]%p*inv[nn-mm]%p;}
    inline int P(int nn,int mm){return (ll)fac[nn]*inv[nn-mm]%p;}
    
    inline int qpow(int A,int B){
    	int res(1);while(B){
    		if(B&1)res=(ll)res*A%p;
    		A=(ll)A*A%p,B>>=1;
    	}return res;
    }
    
    int main(){
    	pw2[1]=2;inv[0]=g[0]=1;
    	fac[0]=fac[1]=pw2[0]=1;
    	for(int i=2;i<N;++i){
    		fac[i]=(ll)fac[i-1]*i%p;
    		pw2[i]=2ll*pw2[i-1]%p;
    		g[i]=2ll*(i-1)*(g[i-1]+g[i-2])%p;
    	}
    	inv[N-1]=qpow(fac[N-1],p-2);
    	for(int i=N-2;i;--i)inv[i]=(ll)inv[i+1]*(i+1)%p;
    	
    	int T,n,k;read(T);
    	while(T--){
    		read(n),read(k);
    		printf("%lld
    ",(ll)C(n,k)*P(n,k)%p *pw2[n]%p *fac[n-k]%p *g[n-k]%p);
    	}return 0;
    }
    
  • 相关阅读:
    【转载】Visual Studio2017中如何设置解决方案中的某个项目为启动项目
    【转载】通过百度站长平台提交网站死链
    【转载】通过搜狗站长平台提交网站域名变更后的文章地址
    【转载】通过搜狗站长平台手动向搜狗搜索提交死链
    【转载】通过搜狗站长平台手动向搜狗搜索提交文章加快收录
    【转载】Visual Studio中WinForm窗体程序如何切换.NET Framework版本
    【转载】Visual Studio2017如何设置打包发布的WinForm应用程序的版本号
    【转载】通过搜狗站长平台查看网站的搜狗流量及搜索关键字
    【转载】Visual Studio2017如何打包发布Winform窗体程序
    【转载】通过百度站长平台查看网站搜索流量及关键字
  • 原文地址:https://www.cnblogs.com/penth/p/10288754.html
Copyright © 2011-2022 走看看