链接
http://www.lydsy.com/JudgeOnline/problem.php?id=2227
题解
这种题作为OI题??我似乎觉得出到数竞题里更合适。
首先这是一个古典概型,概率等于合法的方案数除以总方案数。总方案数=
KN
。
合法方案数的计算:在最后面加一个座位,然后所有的座位连成一个环。现在那么总方案数等于
(K+1)N
,每种环都算了
(K+1)
次,所以除以
(K+1)
,最后抽调一个空白的座位来构造一个合法的方案,所以要乘
(N−K+1)
。
综上所述
ans=(K+1)N−1(N−K+1)KN
分解质因数进行约分,高精度分别计算分子分母即可。(约分之后,对于一个质数,如果是正数幂,就乘到分子上,否则乘到分母上)
代码
//组合数学+高精度
#include <cstdio>
#include <algorithm>
#define ll long long
#define maxn 250
#define maxl 100000
#define ya 100000000
using namespace std;
ll prime[maxn], q[maxn], N, K, mark[maxn], A[maxl], B[maxl];
void shai()
{
ll i, j;
for(i=2;i<maxn;i++)
{
if(!mark[i])prime[++prime[0]]=i;
for(j=1;j<=prime[0] and i*prime[j]<maxn;j++)
{
mark[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
void resolve(ll x, ll d)
{
ll t, i;
for(i=1,t=x;prime[i]<=t;i++)
for(;t%prime[i]==0;t/=prime[i])q[i]+=d;
}
void mult(ll *n, ll x)
{
ll i;
for(i=1;i<=n[0];i++)n[i]*=x;
for(i=1;i<=n[0];i++)n[i+1]+=n[i]/ya,n[i]%=ya;
if(n[n[0]+1])n[0]++;
}
void show(ll *n)
{
ll i, j;
printf("%lld",n[n[0]]);
for(i=n[0]-1;i>0;i--)
{
for(j=ya/10;j>1;j/=10)if(n[i]<j)putchar(48);
printf("%lld",n[i]);
}
}
void work()
{
ll i, j, *n, t;
scanf("%lld%lld",&N,&K);
if(N>K){printf("0 1\n");return;}
for(i=0;i<maxn;i++)q[i]=0;
for(i=0;i<maxl;i++)A[i]=B[i]=0;
resolve(K+1,N-1);
resolve(K-N+1,1);
resolve(K,-N);
A[0]=A[1]=B[0]=B[1]=1;
for(i=1;i<maxn;i++)
{
if(q[i]>0)n=A;
else if(q[i]<0)n=B,q[i]=-q[i];
else continue;
for(t=j=1;j<=q[i];j++)
{
if(t*prime[i]>ya)mult(n,t),t=1;
t*=prime[i];
}
if(t>1)mult(n,t);
}
show(A);putchar(32);show(B);putchar(10);
}
int main()
{
ll T;
shai();
for(scanf("%lld",&T);T;T--)work();
return 0;
}