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