15th 黑龙江省赛 K. Keeping A Secret(排列组合,思维)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了15th 黑龙江省赛 K. Keeping A Secret(排列组合,思维)相关的知识,希望对你有一定的参考价值。
显然需要把深度相同的分开考虑
比如现在考虑深度为 i i i的节点有 k k k个
第 j j j个节点需要排在这 k k k个节点的前 x j x_j xj位置,于是我们先对 x j x_j xj排序
先从小的开始考虑,因为它的限制是最小的,模拟以下会发现方案数为
∏ i = 2 k ( m i n ( k , x j ) − i + 1 ) \\prod\\limits_{i=2}^k(\\rm min(k,x_j)-i+1) i=2∏k(min(k,xj)−i+1)
现在还需要考虑深度 i − 1 i-1 i−1(节点个数为 l a s las las)和深度 i i i层(节点个数为 s i z siz siz)之间的连边关系
显然当第 i i i层的节点排列完毕后,需要分成 l a s las las组,每组可以为空,显然方案数为
( s i z − 1 + l a s l a s − 1 ) \\binom{siz-1+las}{las-1} (las−1siz−1+las)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9+7;
const int maxn = 3e5+10;
int n,ans[maxn],fac[maxn];
vector<int>vec[maxn];
int quick(int x,int n)
{
int ans = 1;
for( ; n ; n>>=1,x=x*x%mod )
if( n&1 ) ans = ans*x%mod;
return ans;
}
int C(int n,int m)
{
if( n<m ) return 0ll;
return fac[n]*quick( fac[m]*fac[n-m]%mod,mod-2 )%mod;
}
signed main()
{
cin >> n;
fac[0] = 1;
for(int i=1;i<=200000;i++) fac[i] = fac[i-1]*i%mod;
for(int i=1;i<=n;i++)
{
int d,x; cin >> d >> x;
vec[d].push_back( x );
}
for(int i=1;i<=n;i++) sort( vec[i].begin(),vec[i].end() );
int ANS = 1, pre = 0;
for(int i=1;i<=n;i++)//枚举每一层
{
int sz = vec[i].size(), res = 1;
for(int j=0;j<sz;j++) vec[i][j] -= pre;
for(int j=0;j<sz;j++)
res = res*( min( sz,vec[i][j] )-j )%mod;
ans[i] = res;
ANS = ANS*res%mod; pre += vec[i].size();
}
for(int i=2;i<=n;i++)
{
if( vec[i].size()==0 ) break;
int siz = vec[i].size(), las = vec[i-1].size();//相当于
//相当于siz个物品分成las组,相当于siz-1个空切割las-1次
ANS = ANS*C( siz-1+las,las-1 )%mod;
}
cout << ANS;
}
以上是关于15th 黑龙江省赛 K. Keeping A Secret(排列组合,思维)的主要内容,如果未能解决你的问题,请参考以下文章