生成树计数 lighting 最终决定用这个模板! (有逆元的模板)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 #define sqr(x) ((x)*(x))
 6 using namespace std;
 7 const int M=10007;
 8 const int N=301;
 9 int inv[M],mat[N][N];
10 void init(){//求逆元
11     inv[1]=1;
12     for(int i=2;i<M;i++)
13         inv[i]=(M-M/i)*inv[M%i]%M;
14 }
15 int det(int c[][N],int n){//求矩阵c的n阶顺序主子式的绝对值
16     int i,j,k,w=0,ans=1;
17     for(i=1;i<=n;i++)
18     for(j=1;j<=n;j++) c[i][j]=(c[i][j]%M+M)%M;
19     for(i=1;i<=n;i++){
20         for(j=i;j<=n;j++)//找出第i行起第i列不为0的行
21             if(c[i][j])break;
22         if(i!=j)
23             swap(c[i],c[j]);
24         ans=ans*c[i][i]%M;
25         for(j=i+1;j<=n;j++)//第j行第i列变为0
26         for(k=n+1;k>i;k--)//该行每列减去第i列的值*d
27             c[j][k]=(c[j][k]-c[i][k]*inv[c[i][i]]%M*c[j][i]%M+M)%M;
28     }
29     return ans;
30 }
31 struct point{
32     int x,y;
33 }p[N];
34 int same(point a,point b,point c){   //判断是否共线
35     return (a.x-c.x)*(b.y-c.y)==(b.x-c.x)*(a.y-c.y)
36     &&min(a.x,c.x)<=b.x&&max(a.x,c.x)>=b.x
37     &&min(a.y,c.y)<=b.y&&max(a.y,c.y)>=b.y;
38 }
39 int main(){
40     init();
41     int t,n,r;
42     scanf("%d",&t);
43     while(t--){
44         memset(mat,0,sizeof mat);
45         scanf("%d%d",&n,&r);
46         for(int i=1;i<=n;i++)
47             scanf("%d%d",&p[i].x,&p[i].y);
48         for(int i=1;i<=n;i++)
49         for(int j=i+1;j<=n;j++)
50             if(sqrt(sqr(p[i].x-p[j].x)+sqr(p[i].y-p[j].y))<=r){//距离不大于r
51                 int ok=1;
52                 for(int k=1;k<=n;k++)
53                     if(k!=i&&k!=j&&same(p[i],p[k],p[j]))
54                         ok=0;
55                 if(ok){//构造Kirchhoff矩阵
56                     mat[i][j]=mat[j][i]=-1;
57                     mat[i][i]++;mat[j][j]++;
58                 }
59             }
60         int ans=det(mat,n-1);
61         printf("%d\n",ans?ans:-1);
62     }
63 }

 

posted @ 2019-10-19 13:22  古比  阅读(148)  评论(0编辑  收藏  举报