• 组合数学+错排问题【p4071】[SDOI2016]排列计数


    Description

    求有多少种长度为 n 的序列 A,满足以下条件:

    1 ~ n 这 n 个数在序列中各出现了一次

    若第 i 个数 A[i] 的值为 i,则称 i 是稳定的。序列恰好有 m 个数是稳定的

    满足条件的序列可能很多,序列数对 10^9+7109+7 取模。

    Input

    第一行一个数 T,表示有 T 组数据。

    接下来 T 行,每行两个整数 n、m。

    Output

    输出 T 行,每行一个数,表示求出的序列数

    组合数+错排问题。

    预处理(fac[i])代表(i)的阶乘.(inv[i])代表(i)的阶乘的逆元。

    (f[i])代表有(i)个数的错排方案数。

    我们的答案就是(C_n^{m} imes f[n-m])

    不难理解的解释.

    注意判断(n==m)输出(1)

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define int long long 
    #define mod 1000000007
    #define R register
    
    using namespace std;
    
    const int gz=1000008;
    
    int fac[gz]={1,1},inv[gz],T,f[gz];
    
    inline void in(int &x)
    {
    	int f=1;x=0;char s=getchar();
    	while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    	while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    	x*=f;
    }
    
    inline int ksm(R int x,R int y)
    {
    	R int res=1;
    	for(;y;y>>=1,x=x*x%mod)
    		if(y&1)res=res*x%mod;
    	return res;
    }
    
    inline int C(R int n,R int m)
    {
    	return (fac[n]%mod*inv[n-m])%mod*(inv[m])%mod;
    }
    
    signed main()
    {
    	f[2]=1;
    	for(R int i=2;i<=gz;i++)fac[i]=fac[i-1]*i%mod;
    	inv[gz]=ksm(fac[gz],mod-2);
    	for(R int i=gz-1;i>=0;i--)inv[i]=((i+1)*inv[i+1])%mod;
    	for(R int i=3;i<=gz;i++)f[i]=(i-1)*(f[i-2]+f[i-1])%mod;
    	in(T);
    	for(R int n,m;T;T--)
    	{
    		in(n),in(m);
    		if(n==m)puts("1");
    		else printf("%lld
    ",((C(n,m)%mod)*(f[n-m]%mod))%mod);
    	}
    }
    
  • 相关阅读:
    eharts入门篇一
    手机侧滑导航栏
    用js+cookie实现商城的购物车功能
    实现文字底部居中
    超出两行或三行显示省略号
    clear-fix清除浮动的两种写法
    sass学习入门篇(三)
    如何回答面试中问到的Hibernate和MyBatis的区别
    设计模式之--单例模式
    设计模式之---工厂模式
  • 原文地址:https://www.cnblogs.com/-guz/p/9892404.html
Copyright © 2020-2023  润新知