RPG的错排

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8387    Accepted Submission(s): 3415


Problem Description
今 年暑假杭电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输入结束。
 

 

Sample Input
1
2
0
 

 

Sample Output
1
 

 

Author
Rabbit
 
 
思路:找n的错排数的规律时花了挺久,规律如下
1  1*1=1
2  1*1=1
3  1*2=2
4  3*3=9
5 4*11=44
6 5*53=265
 
 
那么n的错排数就是:(n-1的错排数+n-2的错排数)*(n-1)
 
猜对一半就算成功,举例子:n=6  1.猜对3个时,从6个中任选3个,剩下的应满足错排,则有c(6,3)*rcd[6-3]  2.猜对4个时,任选4个,剩下的错排,则有c(6,4)*rcd[6-4]   猜对5个时即意味着第六个也猜中,故5,6是有1个
 
网上其实有直接的错排公式:f(n)=(n-1)*( f(n-1) + f(n-2) )
 
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
long long rcd[30];
int n;
void init()//初始化计数每个数的错排个数(即n个数每个都不在自己正确的位置上的种数)
{
    rcd[2]=1;
    rcd[3]=2;
    for(int i=4;i<=25;++i)
    rcd[i]=(rcd[i-1]+rcd[i-2])*(i-1);
}
int getc(int m,int k)
{
    int ans=m;
    for(int i=2;i<=k;++i)
    ans=ans*(m-i+1)/i;
    return ans;
}
void solve()
{
    if(n==1) cout<<1<<endl;
    else if(n==2) cout<<1<<endl;
    else if(n==3) cout<<1<<endl;
    else if(n==4) cout<<7<<endl;
    else{
        long long ans=0,m;
        if(n&1) m=(n>>1)+1;
        else m=n>>1;
        for(int i=m;i<n-1;++i){
            ans+=getc(n,i)*rcd[n-i];
        }
       cout<<ans+1<<endl;
    }

}
int main()
{
    std::ios::sync_with_stdio(false);
    init();
    while(scanf("%d",&n)&&n)
    solve();
}

 

 

Source
posted @ 2015-04-02 21:46  JL_Zhou  阅读(442)  评论(0编辑  收藏  举报