D - RPG的错排

今年暑假杭电ACM集训队第一次组成女生队,其中有一队叫RPG,但做为集训队成员之一的野骆驼竟然不知道RPG三个人具体是谁谁。RPG给他机会让他猜猜,第一次猜:R是公主,P是草儿,G是月野兔;第二次猜:R是草儿,P是月野兔,G是公主;第三次猜:R是草儿,P是公主,G是月野兔;......可怜的野骆驼第六次终于把RPG分清楚了。由于RPG的带动,做ACM的女生越来越多,我们的野骆驼想都知道她们,可现在有N多人,他要猜的次数可就多了,为了不为难野骆驼,女生们只要求他答对一半或以上就算过关,请问有多少组答案能使他顺利过关。

Input

输入的数据里有多个case,每个case包括一个n,代表有几个女生,(n<=25), n = 0输入结束。

Output

1
1

Sample Input

1
2
0

Sample Output

1
1

 思路:

要求一半以上的正确猜对 ,实质上就是让一组序列中,所有错位放置的位置数量不超过一般的加和

所以要做两个工作,n为总数,n/2 为其一半,那么总和就是 Cn_m * 对应取m个数错位放置的总数量 (n 是下标,m是上标)的加和

代码如下:

#include<iostream>
#include<stdio.h>
using namespace std;

typedef long long ll;

// calculate the Cn_m number
ll Cnm(int n,int m){

    ll sum=1;
    for(int i=1;i<=m;i++){
        //sum*=n/i;  there are different!
        sum=sum*n/i;
        n--;
    }
    return sum;
}

int main(){

    const int MAXN =30;

    ll dp[MAXN];
    bool map[MAXN];
    fill(map,map+MAXN,false);

    //calculate the dislocation sorting number
    dp[0]=0;
    dp[1]=0;
    dp[2]=1;
    for(int i=3;i<=MAXN/2;i++){
        dp[i] = (i-1)*(dp[i-1]+dp[i-2]);
    }

    int N;
    while(scanf("%d",&N)!=EOF){
        if(N==0){
            break;
        }

        if (N == 1 || N == 2)
        {
            printf("1\n");
            continue;
        }

        int half_N = N/2;

        ll sum = 0;
        for(int j=half_N;j>=1;j--){

           sum += Cnm(N,j)* dp[j];

        }

        printf("%lld\n",sum+1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Willen_/article/details/85111417