题目链接

题面:

题意:
给定一张图,有左部和右部两部分顶点,对于每一个左部顶点 u i u_i ui 都与右部顶点 v 1 , v 2 , . . . v j v_1,v_2,...v_j v1,v2,...vj右部顶点的一个前缀相连。
问这张图生成树的个数。

题解:

我们设 u i u_i ui 的度数为 λ i \lambda_i λi v j v_j vj 的度数为 λ j \lambda _j ^\prime λj,且满足 λ i > = λ i + 1 , λ i > = λ i + 1 \lambda_i>=\lambda_{i+1},\lambda_i^\prime>=\lambda_{i+1}^\prime λi>=λi+1,λi>=λi+1

x i , y i x_i,y_i xi,yi分别为 u i , v i u_i,v_i ui,vi的权值,一棵生成树T的权值为。
s u m ( T ) = i = 1 n x i d e g T ( u i ) j = 1 m y j d e g T ( v j ) sum(T)=\prod_{i=1}^nx_i^{deg_T(u_i)}\cdot\prod_{j=1}^my_j^{deg_T(v_j)} sum(T)=i=1nxidegT(ui)j=1myjdegT(vj)

( G ) = T s u m ( T ) \sum (G)=\sum_Tsum(T) (G)=Tsum(T)

则生成树的个数 c n t ( G ) = ( G ) x 1 = x 2 = . . . = x n = y 1 = y 2 = . . . = y m = 1 cnt(G)=\sum(G)|_{x_1=x_2=...=x_n=y_1=y_2=...=y_m=1} cnt(G)=(G)x1=x2=...=xn=y1=y2=...=ym=1

论文给出:
( G ) = x 1 x 2 . . . x n y 1 y 2 . . . y m i = 2 n ( y 1 + y 2 + . . . + y λ i ) j = 2 m ( x 1 + x 2 + . . . + x λ j ) \sum(G)=x_1*x_2*...*x_n*y_1*y_2*...*y_m*\prod_{i=2}^n(y_1+y_2+...+y_{\lambda_i})*\prod_{j=2}^m(x_1+x_2+...+x_{\lambda_{j}^\prime}) (G)=x1x2...xny1y2...ymi=2n(y1+y2+...+yλi)j=2m(x1+x2+...+xλj)

若所有的 x 与 y 均取 1。
c n t ( G ) = i = 2 n λ i j = 2 m λ j cnt(G)=\prod_{i=2}^n\lambda_i\cdot\prod_{j=2}^m\lambda_j^\prime cnt(G)=i=2nλij=2mλj

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=100100;
const int maxm=100100;
const int up=100000;

ll a[maxn],b[maxn];
int main(void)
{
    int n,m,p;
    while(scanf("%d%d%d",&n,&m,&p)!=EOF)
    {
        for(int i=1;i<=m;i++)
            b[i]=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),b[1]++,b[a[i]+1]--;
        for(int i=1;i<=m;i++)
            b[i]+=b[i-1];
        sort(a+1,a+n+1);
        sort(b+1,b+m+1);
        ll ans=1;
        for(int i=n-1;i>=1;i--) ans=ans*a[i]%p;
        for(int i=m-1;i>=1;i--) ans=ans*b[i]%p;
        printf("%lld\n",ans);
    }
    return 0;
}