• bzoj4894 天赋


    Description

    小明有许多潜在的天赋,他希望学习这些天赋来变得更强。正如许多游戏中一样,小明也有n种潜在的天赋,但有一些天赋必须是要有前置天赋才能够学习得到的。也就是说,有一些天赋必须是要在学习了另一个天赋的条件下才能学习的。比如,要想学会"开炮",必须先学会"开枪"。一项天赋可能有多个前置天赋,但只需习得其中一个就可以学习这一项天赋。上帝不想为难小明,于是小明天生就已经习得了1号天赋-----"打架"。于是小明想知道学习完这n种天赋的方案数,答案对1,000,000,007取模。

    Input

    第一行一个整数n。
    接下来是一个n*n的01矩阵,第i行第j列为1表示习得天赋j的一个前置天赋为i。
    数据保证第一列和主对角线全为0。
    n<=300

    Output

    第一行一个整数,问题所求的方案数。

    Sample Input

    8
    01111111
    00101001
    01010111
    01001111
    01110101
    01110011
    01111100
    01110110

    Sample Output

    72373
     
    正解:矩阵树定理+高斯消元。
    有向图树形图计数问题。。
    假设边的方向是从根往叶子,那么需要消元的矩阵变成入度矩阵-邻接矩阵,同时必须去掉根的那一行和那一列再求行列式。
     
     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define rhl (1000000007)
     6 
     7 using namespace std;
     8 
     9 int d[305][305],g[305][305],n,ans;
    10 
    11 il int gi(){
    12   RG int x=0,q=1; RG char ch=getchar();
    13   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    14   if (ch=='-') q=-1,ch=getchar();
    15   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    16   return q*x;
    17 }
    18 
    19 il char gc(){
    20   RG char ch=getchar();
    21   while (ch!='0' && ch!='1') ch=getchar();
    22   return ch;
    23 }
    24 
    25 il int qpow(RG int a,RG int b){
    26   RG int ans=1;
    27   while (b){
    28     if (b&1) ans=1LL*ans*a%rhl;
    29     a=1LL*a*a%rhl,b>>=1;
    30   }
    31   return ans;
    32 }
    33 
    34 il void gauss(){
    35   for (RG int i=2,id;i<=n;++i){
    36     for (id=i;id<=n;++id) if (d[id][i]!=0) break;
    37     for (RG int j=2;j<=n;++j) swap(d[i][j],d[id][j]);
    38     RG int inv=qpow(d[i][i],rhl-2);
    39     for (RG int j=i+1;j<=n;++j){
    40       RG int tmp=d[j][i];
    41       for (RG int k=i;k<=n;++k){
    42     d[j][k]+=rhl-1LL*d[i][k]*inv%rhl*tmp%rhl;
    43     if (d[j][k]>=rhl) d[j][k]-=rhl;
    44       }
    45     }
    46     ans=1LL*ans*d[i][i]%rhl;
    47   }
    48   return;
    49 }
    50 
    51 int main(){
    52 #ifndef ONLINE_JUDGE
    53   freopen("talent.in","r",stdin);
    54   freopen("talent.out","w",stdout);
    55 #endif
    56   n=gi(),ans=1;
    57   for (RG int i=1;i<=n;++i)
    58     for (RG int j=1;j<=n;++j) g[i][j]=gc()=='1';
    59   for (RG int i=1,tmp=0;i<=n;++i,tmp=0){
    60     for (RG int j=1;j<=n;++j) tmp+=g[j][i];
    61     d[i][i]=tmp;
    62   }
    63   for (RG int i=1;i<=n;++i)
    64     for (RG int j=1;j<=n;++j)
    65       (d[i][j]+=rhl-g[i][j])%=rhl;
    66   gauss(),cout<<ans; return 0;
    67 }
  • 相关阅读:
    HDOJ 1202 The calculation of GPA
    HDOJ 1197 Specialized Four-Digit Numbers
    HDOJ 1196 Lowest Bit(二进制相关的简单题)
    HDOJ 1194 Beat the Spread!(简单题)
    NOIP2018游记
    CF1043
    洛谷P1280 尼克的任务
    洛谷P1155 双栈排序
    SPOJ6340 ZUMA
    chessboard
  • 原文地址:https://www.cnblogs.com/wfj2048/p/8143520.html
Copyright © 2020-2023  润新知