P4609 [FJOI2016]建筑师

本文针对洛谷P4609题目提供了一种解决方案,通过组合数学中的第一类斯特林数与组合数计算特定排列组合的数量,适用于算法竞赛中的计数问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面:https://www.luogu.org/problemnew/show/P4609

考虑先把最大值放了以后,左边a-1个圆排列,右边b-1个圆排列。
直接就是C(a-1+b-1,a-1)*S(n-1,a-1+b-1)。
S为第一类斯特林数。

#include<iostream>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#define N 55000
#define M 220
#define eps 1e-7
#define inf 1e9+7
#define db double
#define ll long long
#define ldb long double
using namespace std;
inline ll read()
{
    char ch=0;
    ll x=0,flag=1;
    while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*flag;
}
const ll mo=1e9+7;
ll fac[N],vac[N],s[N][M];
ll c(ll n,ll m){return fac[n]*vac[m]%mo*vac[n-m]%mo;}
ll ksm(ll x,ll k){ll ans=1;while(k){if(k&1)ans=ans*x%mo;k>>=1;x=x*x%mo;}return ans;}
void work()
{
    ll n=read(),a=read(),b=read();
    if(a+b>n+1)printf("0\n");
    else printf("%lld\n",(c(a-1+b-1,a-1)*s[n-1][a-1+b-1])%mo);
}
int main()
{
    fac[0]=vac[0]=s[0][0]=1;
    for(ll i=1;i<=50000;i++)
    {
        fac[i]=fac[i-1]*i%mo;
        vac[i]=vac[i-1]*ksm(i,mo-2)%mo;
        for(ll j=1;j<=200;j++)
        s[i][j]=((s[i-1][j]*(i-1)%mo)+s[i-1][j-1])%mo;
    }
    ll t=read();
    for(ll i=1;i<=t;i++)work();
    return 0;
}

转载于:https://www.cnblogs.com/Creed-qwq/p/10618909.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值