今年暑假杭电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是上标)的加和
https://blog.csdn.net/qq_18661257/article/details/47663825
代码如下:
#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;
}
最终的sum+1 是因为 全部位置都是正确的时候,是没有放入计算的,所以要另外加上。