http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=61975
题目意思明了,就是统计+排序,求前k个之和, 另一个要求的答案是求组合数C(n,m)
n<=26 阶乘的话__int64 在26之前就爆了,因此 求n到k的阶乘/k的阶层就好,然后有一点要注意的是 如果求C(26,15) 15!会爆掉 所以得变成C(26,11) 阶乘到13之前都不会爆
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
__int64 vis[28];
char tm[100000+6];
__int64 min(__int64 a,__int64 b)
{
if (a<b)
return a;
return b;
}
__int64 zuhe (__int64 p,__int64 q)
{
q=min(q,p-q);
__int64 i;
__int64 fac1=1;
for (i=p;i>=p+1-q;i--) //p!
fac1*=i;
__int64 fac2=1;
for (i=1;i<=q;i++) //q!
fac2*=i;
return (fac1/fac2);
}
__int64 cmp(__int64 a,__int64 b)
{
return a>b;
}
int main()
{
// printf("%I64d\n",zuhe(26,15));
__int64 i;
memset(vis,0,sizeof (vis));
scanf("%s",tm+1);
__int64 len=strlen(tm+1);
for (i=1;i<=len;i++)
{
vis [ tm[i]-'a'+1 ]++;
}
sort(vis+1,vis+1+26,cmp);
__int64 kind=0;
for (i=1;i<=26;i++)
{
if (vis[i])
kind++;
else break;
}
__int64 k;
scanf("%I64d",&k);
if (k>=kind)
{
printf("%I64d 1\n",len);
return 0;
}
else
{
__int64 sum=0;
for (i=1;i<=k;i++)
{
sum+=vis[i];
}
__int64 minn=vis[k];
__int64 cun1=0;
__int64 cun2=0;
for (i=1;i<=k;i++)
{
if (minn==vis[i])
cun1++;
}
for (i=1;i<=26;i++)
{
if (minn==vis[i])
cun2++;
}
__int64 ans=zuhe(cun2,cun1);
printf("%I64d %I64d\n",sum,ans);
}
return 0;
}