Eddy's AC难题
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7109 Accepted Submission(s): 3392
Problem Description
Eddy是个ACMer,他不仅喜欢做ACM题,而且对于Ranklist中每个人的ac数量也有一定的研究,他在无聊时经常在纸上把Ranklist上每个人的ac题目的数量摘录下来,然后从中选择一部分人(或者全部)按照ac的数量分成两组进行比较,他想使第一组中的最小ac数大于第二组中的最大ac数,但是这样的情况会有很多,聪明的你知道这样的情况有多少种吗?
特别说明:为了问题的简化,我们这里假设摘录下的人数为n人,而且每个人ac的数量不会相等,最后结果在64位整数范围内.
Input
输入包含多组数据,每组包含一个整数n,表示从Ranklist上摘录的总人数。
Output
对于每个实例,输出符合要求的总的方案数,每个输出占一行。
Sample Input
2
4
Sample Output
1
17
思路:
(1)当n=2时,f=C(2,2)*1=1;
(2)当n=3时,f=C(3,2)*1+C(3,3)*2=5;
(3)当n=4时,f=C(4,2)*1+C(4,3)*2+C(4,4)*3=17;
(4)当n=5时,f=C(5,2)*1+C(5,3)*2+C(5,4)*3+C(5,5)*4=49;
依此类推:公式:f=C(n,2)*1+C(n,3)*2+…+C(n,n)*(n-1);
#include<iostream>
using namespace std;
long long int gcd(long long int x,long long int y)
{
if(y==0)
return x;
else
return gcd(y,x%y);
}
long long int fun(long long int a,long long int b)
{
long long int s=1,t=1,t1,cnt=1,i,j;
for(i=b+1;i<=a;i++)
{
s=s*i;
for(j=cnt;j<=(a-b);j++)
{
t=t*j;
t1=gcd(s,j);
s=s/t1;
t=t/t1;
if(s<t)
{
cnt=j+1;
break;
}
}
if(j==((a-b)+1))
{
cnt=(a-b)+1;
}
}
return s/t;
}
int main()
{
long long int n,res=1,t,i,s=0;
while(cin>>n)
{
s=0;
for(i=2;i<=n;i++)
{
s=s+fun(n,i)*(i-1);
}
cout<<s<<endl;
}
}