CodeForces 888 D.Almost Identity Permutations(组合数学)

Description

给出 n,k ,问长度为 n 的排列中满足至少有 nk 个不动点的排列个数

Input

两个整数 n,k(1n1000,1k4)

Output

输出满足条件的排列数

Sample Input

4 1

Sample Output

1

Solution

对于 n 个位置的错位排列数 Dn 满足关系 Dn=(n1)(Dn1+Dn2) ,求得 D2=1,D3=2,D4=9

k=1 时,因为不可能 n1 个不动点,故只有 pi=i,1in 满足条件,答案为 1

k=2 时,只有两个位置不是不动点是可以做到的,从 n 个位置中选两个互换,其他位置不动即可,方案数 C2n

k=3 时,只有三个位置不是不动点,首先选出三个位置方案数 C3n ,三个元素的错位排列数是 2 ,方案数 2C3n

k=4 时,只有四个位置不是不动点,首先选出四个位置的方案数 C4n ,四个元素的错位排列数是 9 ,方案数 9C4n

Code

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100001;
ll C(int n,int m)
{
    if(m==1)return n;
    if(m==2)return n*(n-1)/2;
    if(m==3)return n*(n-1)*(n-2)/6;
    if(m==4)return (ll)n*(n-1)*(n-2)*(n-3)/24;
}
int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        ll ans=0;
        if(k>=1)ans+=1;
        if(k>=2)ans+=C(n,2);
        if(k>=3)ans+=2ll*C(n,3);
        if(k>=4)ans+=9ll*C(n,4);
        printf("%I64d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(Code,Forces,组合数学)