zoukankan      html  css  js  c++  java
  • 【51NOD1806】wangyurzee的树(Prufer编码,容斥原理,组合计数)

    题意:有n个点和m条限制,每条限制限制了一个点的度数不能为某个数。

    求合法的树的个数模10^9+7

    n<=10^6

    m<=17

    思路:WYZ作业

    首先m<=17显然是2^m容斥

    枚举每一个限制有用或没用,考虑某一个约束情况下的方案数

    Caylay定理:n个点的生成树的个数=n^(n-2)

    Prufer序列:一个长度为n-2的Prufer序列对应唯一的一棵n个节点的树,度数为a[i]的点在其中出现了(a[i]-1)次

    考虑先在序列中填上所有的受约束条件的点,它们的方案数是C(n-2,a[1]-1)*C(n-2-(a[1]-1),a[2]-1)*……

    化简得:

    (n-2)!/((a[1]-1)!(a[2]-1)!……*(n-2-sigma(a[i]-1))!)

    考虑没有约束的点可以随意在剩下的序列中出现,它们的方案数为:

    (n-p)^(n-2-sigma(a[i]-1))

    其中p为选中的约束条件个数

    将两部分相乘,根据p的奇偶性进行容斥计算即可

    几个hack点:

    1.对于同一个点可能会有多个约束条件,需要判断某一个点是否被多次限制,如果被多次限制就不能计入答案

    2.n=1需要特判ans=1(真的吗,这个点可是坑了我5点头盾

     1 const mo=1000000007;
     2 var flag:array[1..1000000]of longint;
     3     fac,exf:array[0..1000000]of int64;
     4     a,b,c:array[1..17]of longint;
     5     n,m,i:longint;
     6     sun:int64;
     7 
     8 function mult(x,y:longint):int64;
     9 var tmp:int64;
    10 begin
    11  tmp:=x; mult:=1;
    12  while y>0 do
    13  begin
    14   if y and 1=1 then mult:=mult*tmp mod mo;
    15   tmp:=tmp*tmp mod mo;
    16   y:=y>>1;
    17  end;
    18 end;
    19 
    20 procedure dfs(k:longint);
    21 var i,j,tot,sum:longint;
    22     ans:int64;
    23 begin
    24  if k=m+1 then
    25  begin
    26   tot:=0; ans:=fac[n-2]; sum:=n-2;
    27   for i:=1 to m do
    28    if c[i]>0 then
    29    begin
    30     inc(tot);
    31     inc(flag[a[i]]);
    32     sum:=sum-(b[i]-1);
    33    end;
    34   for i:=1 to m do
    35    if (c[i]>0)and(flag[a[i]]>1) then
    36    begin
    37     for j:=1 to m do
    38      if c[j]>0 then dec(flag[a[j]]);
    39     exit;
    40    end;
    41   for i:=1 to m do
    42    if c[i]>0 then ans:=ans*exf[b[i]-1] mod mo;
    43   //writeln(sum);
    44   if sum>=0 then
    45   begin
    46    ans:=ans*exf[sum] mod mo;
    47    ans:=ans*mult(n-tot,sum) mod mo;
    48    if tot and 1=0 then sun:=(sun+ans) mod mo
    49     else sun:=(sun-ans) mod mo;
    50    sun:=(sun+mo) mod mo;
    51   end;
    52   for i:=1 to m do
    53    if c[i]>0 then dec(flag[a[i]]);
    54   exit;
    55  end;
    56  if b[k]=0 then dfs(k+1)
    57   else
    58   begin
    59    c[k]:=1;
    60    dfs(k+1);
    61    c[k]:=0;
    62    dfs(k+1);
    63   end;
    64 end;
    65 
    66 begin
    67  assign(input,'51nod1806.in'); reset(input);
    68  assign(output,'51nod1806.out'); rewrite(output);
    69  readln(n,m);
    70  if n=1 then
    71  begin
    72   writeln(1);
    73   exit;
    74  end;
    75  for i:=1 to m do read(a[i],b[i]);
    76  exf[0]:=1; exf[1]:=1; fac[0]:=1;
    77  for i:=1 to 1000000 do fac[i]:=fac[i-1]*i mod mo;
    78  for i:=2 to 1000000 do exf[i]:=exf[mo mod i]*(mo-mo div i) mod mo;
    79  for i:=1 to 1000000 do exf[i]:=exf[i-1]*exf[i] mod mo;
    80  dfs(1);
    81  writeln(sun);
    82  close(input);
    83  close(output);
    84 end.
  • 相关阅读:
    [Spring框架]Spring 事务管理基础入门总结.
    [Maven]Eclipse插件之Maven配置及问题解析.
    编程哲学的几点感悟
    用ASP.NET Core MVC 和 EF Core 构建Web应用 (十)
    用ASP.NET Core MVC 和 EF Core 构建Web应用 (九)
    C# 中的特性 Attribute
    用ASP.NET Core MVC 和 EF Core 构建Web应用 (八)
    用ASP.NET Core MVC 和 EF Core 构建Web应用 (七)
    C# 调用 WebApi
    用ASP.NET Core MVC 和 EF Core 构建Web应用 (六)
  • 原文地址:https://www.cnblogs.com/myx12345/p/6624038.html
Copyright © 2011-2022 走看看