• [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);
    }
  • 相关阅读:
    Asp.net Core 6.0 如何在开发时动态更新cshtml (开发篇)
    .NET Core 中正确使用 HttpClient 的姿势
    SQLite Entity Framework Core 使用 DBFirst
    c# 解析xml
    asp.net core 6 发布到IIS后打开开发模式(错误信息显示出来)
    linq to entity group by 时间
    Kubernetes——StatefulSet控制器——案例:etcd集群
    Kubernetes——访问控制
    C++正则表达式
    find、find_if、find_first_of、find_if_not、search、二分查找
  • 原文地址:https://www.cnblogs.com/coco-night/p/9664399.html
Copyright © 2020-2023  润新知