• 【LOJ6044】「雅礼集训 2017 Day8」共(prufer序列)


    点此看题面

    • 求有多少棵(n)个点的、以(1)号点为根的有根树,满足恰好有(k)个点深度为奇数((1)号点深度为(1))。
    • (nle5 imes10^5),当(n>10^3)时模数为(998244353)

    (prufer)序列的经典应用

    首先有一个组合数(C_{n-1}^{k-1}),表示从除(1)之外的点中选出剩余的深度为奇数的点的方案数。

    由于只可能奇数度数和偶数度数的点之间存在边,且每对奇数度数和偶数度数的点之间都可能存在边,因此我们现在有一张两边点数分别是(k)(n-k)的完全二分图。

    然后就可以借鉴【BZOJ4766】文艺计算姬的结论,这样一张图中的生成树个数就是(k^{n-k-1}cdot(n-k)^{k-1})

    代码:(O(n^2)/O(n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define BN 1000
    using namespace std;
    int n,k,X;I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
    I int Fac(RI x) {RI t=1;W(x) t=1LL*t*(x--)%X;return t;}//暴力算阶乘
    int c[BN+5][BN+5];I int C(CI x,CI y)//组合数
    {
    	if(x<=BN) {for(RI i=c[0][0]=1;i<=x;++i) for(RI j=c[i][0]=1;j<=i;++j) c[i][j]=(c[i-1][j-1]+c[i-1][j])%X;return c[x][y];}//暴力求组合数
    	else return 1LL*Fac(x)*QP(1LL*Fac(y)*Fac(x-y)%X,X-2)%X;//x>BN时必定有逆元,套用组合数计算公式
    }
    int main()
    {
    	return scanf("%d%d%d",&n,&k,&X),printf("%d
    ",1LL*C(n-1,k-1)*QP(k,n-k-1)%X*QP(n-k,k-1)%X),0;//选点方案×建树方案
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    403
    311
    401
    310
    308
    309
    307
    304
    3-1
    2-11
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/LOJ6044.html
Copyright © 2020-2023  润新知