goj1008 递推+组合

22 篇文章 0 订阅

这道题与以往的递归不太一样,首先递归式子包括组合数,基本第归式是C(m,nf(n)。f(n)为n个人的全错排,全错排可以理解为所有的排列,然后减去反面的情况。即,一个人排对的情况,两个人排对的地方....全排对的情况.。这个可以用公式C(n,m)*right(n-m)(m取1...n)递归得出。然后递归的函数也与以前打的不一样内部含有一个循环。

#include<cstdio>
using namespace std;
int c,n,m;

long long O(int n){
    if(n==1)
        return 1;
   return n*O(n-1);
}

long long A(int n,int m){///n>m
    if(m==n)
        return O(m);
    return O(n)/O(n-m);
}

long long C(int n,int m){
    return A(n,m)/O(m);
}

long long solve(int m){
    if(m==2)
        return 1;
    long long sum=0;///sum要在里面定义,因为这个sum是对应一个人数时的反面的加和。
    for(int i=1;i<m-1;i++)
        sum+=C(m,i)*solve(m-i);
    return O(m)-(sum+1);
}

int main(){
   while(scanf("%d",&c)!=EOF){
   for(int i=0;i<c;i++){
    scanf("%d%d",&n,&m);
    long long ans=C(n,m)*(solve(m));
    printf("%lld\n",ans);
   }
   }
   return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值