生成树计数 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 }