zoukankan      html  css  js  c++  java
  • [2016北京集训试题8]五颜六色的幻想乡-[拉格朗日插值+矩阵树定理]

    Description

    Solution

    假如将图中所有红边一条拆为x条,蓝边一条拆为y条,可得:

    $A_{x,y}=sum_{r=0}^{n-1}sum_{b=0}^{n-1-r}*T_{r,b}*x^{r}*y^{b} $

    其中$A_{x,y}$是拆完边后,用矩阵树定理求出的生成树个数,$T_{r,b}$是用r条红边,b条蓝边的生成树个数。

    然后就是拉格朗日插值了,已知点值$A_{x,y}$,求$T_{r,b}$。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int mod=1e9+7;
    int n,m;
    int x[10010],y[10010],col[10010];
    ll c[60][60];
    ll ksm(ll x,int k)
    {ll re=1;while(k){if (k&1) re=re*x%mod;k>>=1;x=x*x%mod;}return re;}
    ll gauss()
    {
        int op=1,i,j,now;ll js,t,ans=1;
        for (i=1;i<n;i++)
        {
            for (j=i;j<n&&!c[j][i];j++);
            if (j==n) return 0;
            now=j;
            if (now!=i) for (op=-op,j=i;j<n;j++) swap(c[i][j],c[now][j]);
            js=ksm(c[i][i],mod-2);        
            for (int j=i+1;j<n;j++)
            {
                t=js*c[j][i]%mod;
                for (int k=i;k<n;k++)
                {
                    c[j][k]-=t*c[i][k]%mod;
                    if (c[j][k]>mod) c[j][k]-=mod;if (c[j][k]<0) c[j][k]+=mod;
                }
                
            }
            ans=ans*c[i][i]%mod;
        }
        return op==1?ans:mod-ans;
    }
    ll t;
    ll f[60][60],fx[60],fy[60],ans[60][60];
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++) scanf("%d%d%d",&x[i],&y[i],&col[i]);
        for (int i=1;i<=n;i++) for (int j=1;j<=n;j++)
        {
            memset(c,0,sizeof(c));
            for (int k=1;k<=m;k++)
            {
                if (col[k]==1) t=i;else if (col[k]==2) t=j;else t=1;
                c[x[k]][x[k]]+=t;c[y[k]][y[k]]+=t;
                c[x[k]][y[k]]-=t;c[y[k]][x[k]]-=t;
            }
            f[i][j]=gauss();
        }
        for (int i=1;i<=n;i++) for (int j=1;j<=n;j++)
        {
            t=f[i][j];
            memset(fx,0,sizeof(fx));memset(fy,0,sizeof(fy));
            fx[0]=fy[0]=1;
            for (int k=1;k<=n;k++) if (k!=i)
            {
                for (int x=n;x;x--) fx[x]=(fx[x-1]-fx[x]*k)%mod;
                (fx[0]*=-k)%=mod;
                (t*=ksm(i-k,mod-2))%=mod;
            }
            for (int k=1;k<=n;k++) if (k!=j)
            {
                for (int x=n;x;x--) fy[x]=(fy[x-1]-fy[x]*k)%mod;
                (fy[0]*=-k)%=mod;
                (t*=ksm(j-k,mod-2))%=mod;
            }
            for (int x=0;x<=n;x++) for (int y=0;y<=n-x;y++) (ans[x][y]+=t*fx[x]%mod*fy[y])%=mod;
        }
        for (int x=0;x<n;x++) for (int y=0;y<n-x;y++) printf("%lld
    ",(ans[x][y]+mod)%mod);
    }
  • 相关阅读:
    我所理解的执行力
    iOS移动开发周报-第20期
    iOS移动开发周报-第19期
    iOS开发如何提高
    iOS移动开发周报-第18期
    iOS移动开发周报-第17期
    一起入门python3之元组和数列
    提权笔记本
    sqlmap笔记本
    SQL注入自学[第一学:一个简单的注入环境的编写]
  • 原文地址:https://www.cnblogs.com/coco-night/p/9664399.html
Copyright © 2011-2022 走看看