小明有许多潜在的天赋,他希望学习这些天赋来变得更强。正如许多游戏中一样,小明也有n种潜在的天赋,但有
一些天赋必须是要有前置天赋才能够学习得到的。也就是说,有一些天赋必须是要在学习了另一个天赋的条件下才
能学习的。比如,要想学会"开炮",必须先学会"开枪"。一项天赋可能有多个前置天赋,但只需习得其中一个就可
以学习这一项天赋。上帝不想为难小明,于是小明天生就已经习得了1号天赋-----"打架"。于是小明想知道学习完
这n种天赋的方案数,答案对1,000,000,007取模。
第一行一个整数n。
接下来是一个n*n的01矩阵,第i行第j列为1表示习得天赋j的一个前置天赋为i。
数据保证第一列和主对角线全为0。
n<=300
1 #include<iostream>
2 #include<algorithm>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #define LL long long
7 using namespace std;
8 const int mod=1e9+7;
9 const int mxn=305;
10 int f[mxn][mxn];
11 int n;
12 char s[mxn];
13 int ksm(int a,int k){
14 int res=1;
15 while(k){
16 if(k&1)res=(LL)res*a%mod;
17 a=(LL)a*a%mod;
18 k>>=1;
19 }
20 return res;
21 }
22 int solve(int n){
23 int i,j,k,F=1;
24 for(i=1;i<=n;i++){
25 int p=i;
26 for(j=i;j<=n;j++)if(f[j][i]){p=i;break;}
27 if(p!=i){for(j=1;j<=n;j++)swap(f[p][j],f[i][j]); F=-F;}
28 for(j=i+1;j<=n;j++){
29 LL inv=(LL)f[j][i]*ksm(f[i][i],mod-2)%mod;
30 for(k=i;k<=n;k++){
31 f[j][k]=((LL)f[j][k]-inv*(LL)f[i][k]%mod+mod)%mod;
32 }
33 }
34 }
35 int res=F;
36 for(i=1;i<=n;i++)res=(LL)res*f[i][i]%mod;
37 if(res<0)res+=mod;
38 return res;
39 }
40 int main(){
41 int i,j;
42 scanf("%d",&n);
43 for(i=1;i<=n;i++){
44 scanf("%s",s+1);
45 for(j=1;j<=n;j++){
46 if(s[j]==‘1‘){
47 f[j][j]++;
48 f[i][j]--;
49 }
50 }
51 }
52 for(i=1;i<=n;i++)
53 for(j=1;j<=n;j++)
54 f[i][j]=f[i+1][j+1];
55 LL ans=solve(n-1);
56 printf("%lld\n",ans);
57 return 0;
58 }