• codeforces 917D Stranger Trees


    题目链接

    正解:矩阵树定理+拉格朗日插值。

    一下午就搞了这一道题,看鬼畜英文题解看了好久。。

    首先这题出题人给了两种做法,感觉容斥+$prufer$序列+$dp$的做法细节有点多所以没看,然而这个做法似乎更难想。。

    我们先构造一个函数$f(x)$,表示用一个完全图和$x-1$棵原树的边,构成的生成树的方案数。

    也就是说,原树的每条边复制成$x$条,不在原树的边都变成一条边,求这个图的生成树的方案数。

    然后我们可以发现,这个方案数实际上就等于$sum_{i=0}^{n-1}x^{i}*ans_{i}$,其中$ans_{i}$表示询问的恰好有$i$条边的答案。

    稍微解释一下,我们选定了原树的$i$条边,那么原树这$i$条边每条边就有$x$种选择,其他边只有$1$种选择。

    然后现在我们的目标就变成了求出这个函数所表示的多项式的系数。

    那么我们可以算出$x$取$[1,n]$的答案,用拉格朗日插值求出多项式,计算答案可以用矩阵树定理。

    复杂度为$O(n^{4}+n^{3})$,写完题解以后发现也不是很难。。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define rhl (1000000007)
     6 #define N (105)
     7 
     8 using namespace std;
     9 
    10 int a[N][N],g[N][N],p[N],ans[N],fac[N],ifac[N],inv[N],n,len;
    11 
    12 il int gi(){
    13   RG int x=0,q=1; RG char ch=getchar();
    14   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    15   if (ch=='-') q=-1,ch=getchar();
    16   while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    17   return q*x;
    18 }
    19 
    20 il int qpow(RG int a,RG int b){
    21   RG int ans=1;
    22   while (b){
    23     if (b&1) ans=1LL*ans*a%rhl;
    24     if (b>>=1) a=1LL*a*a%rhl;
    25   }
    26   return ans;
    27 }
    28 
    29 il int gauss(){
    30   RG int res=1;
    31   for (RG int i=1,id,inv;i<n;++i){
    32     for (id=i;id<n && !a[id][i];++id); if (id>=n) return 0;
    33     if (id!=i){
    34       for (RG int j=1;j<n;++j) swap(a[i][j],a[id][j]);
    35       res=-res;
    36     }
    37     res=1LL*res*a[i][i]%rhl,inv=qpow(a[i][i],rhl-2);
    38     for (RG int j=i+1,tmp;j<n;++j){
    39       if (!a[j][i]) continue;
    40       tmp=1LL*a[j][i]*inv%rhl;
    41       for (RG int k=i;k<n;++k)
    42     a[j][k]=(a[j][k]-1LL*a[i][k]*tmp)%rhl;
    43     }
    44   }
    45   return (res+rhl)%rhl;
    46 }
    47 
    48 int main(){
    49 #ifndef ONLINE_JUDGE
    50   freopen("stranger.in","r",stdin);
    51   freopen("stranger.out","w",stdout);
    52 #endif
    53   n=gi(),fac[0]=ifac[0]=1;
    54   for (RG int i=1;i<=n;++i){
    55     inv[i]=i==1?1:1LL*(rhl-rhl/i)*inv[rhl%i]%rhl;
    56     fac[i]=1LL*fac[i-1]*i%rhl;
    57     ifac[i]=1LL*ifac[i-1]*inv[i]%rhl;
    58   }
    59   for (RG int i=1,u,v;i<n;++i)
    60     u=gi(),v=gi(),g[u][v]=g[v][u]=1;
    61   for (RG int k=1;k<=n;++k){
    62     for (RG int i=1;i<=n;++i)
    63       for (RG int j=1;j<=n;++j) a[i][j]=0;
    64     for (RG int i=1;i<n;++i)
    65       for (RG int j=i+1,tmp;j<=n;++j){
    66     tmp=g[i][j] ? k : 1;
    67     a[i][j]-=tmp,a[j][i]-=tmp;
    68     a[i][i]+=tmp,a[j][j]+=tmp;
    69       }
    70     p[len=0]=1LL*gauss()*ifac[k-1]%rhl*ifac[n-k]%rhl;
    71     if ((n-k)&1) p[0]=rhl-p[0];
    72     for (RG int t=1,tmp;t<=n;++t){
    73       if (k==t) continue; tmp=rhl-t;
    74       for (RG int i=++len;~i;--i)
    75     p[i]=(1LL*tmp*p[i]+(i?p[i-1]:0))%rhl;
    76     }
    77     for (RG int i=0;i<=len;++i){
    78       ans[i]+=p[i],p[i]=0; if (ans[i]>=rhl) ans[i]-=rhl;
    79     }
    80   }
    81   for (RG int i=0;i<n;++i) printf("%d ",ans[i]); return 0;
    82 }
  • 相关阅读:
    Ubuntu下安装了java但启动eclipse报错说没装java
    Servlet之Filter详解
    使用mybatis-generator自动生成model、dao、mapping文件
    深入浅出MyBatis
    彻底理解字符编码
    Java多线程系列
    【Swagger2】解决swagger文档地址请求404的问题
    【Git】Git如何合并某一次commit的内容到指定分支
    【Iterm2】如何解决iterm2窗口自动隐藏的问题
    【Git】.DS_Store 是什么文件
  • 原文地址:https://www.cnblogs.com/wfj2048/p/8469939.html
Copyright © 2020-2023  润新知