这道题题意:
有很多机器人,机器人可能被闪电打中,被电到的机器人可以传导电到半径为R的其他机器人上,但是要求两个机器人之间不能有其他机器人
每次传递,只能由其中一个机器人传递给另一个,任意机器人可以作为起点。
问所有机器人被电到能形成几种图形,
有些机器人不能电到输出-1
解题:
1. 用计算几何处理,把相互可达的点记录下来用假设Dist[i][j]=1 表示i,j可达
dist[i][j] = 0表示i,j不可达,i=j,dist[i][j]=0;
2. 有个生成树计数算法。百度一下,
意思是A[i][j] i!=j A[i][j] =0;
i==j A[i][i]表示与i相连的边数
另D = A-Dist
则D的任意一个n-1阶的行列式就是答案。
高斯消元算行列式
3. 数字可能很大要取模
要计算逆元 求a关于p的逆元
另ax+py=1
x就是a的逆元
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<math.h> using namespace std; #define ll long long #define maxn 307 #define mod 10007 struct Point{ int x,y; Point (int x=0,int y=0):x(x),y(y){} }; int Length(Point a){ return a.x*a.x+a.y*a.y; } Point operator-(Point a,Point b){ return Point(a.x-b.x,a.y-b.y); } int Cross(Point a,Point b){ return a.x*b.y-a.y*b.x; } int Dot(Point a,Point b){ return a.x*b.x+a.y*b.y; } int Onsegment(Point a,Point b,Point c){ if(Cross(a-c,b-c) != 0) return 0; if(Dot(a-b,a-c) < 0) return 1; return 0; } Point point[maxn]; int dist[maxn][maxn]; void getDist(int n,int r){ memset(dist,0,sizeof(dist)); int flag ; for(int i = 0;i < n; i++){ for(int j = i+1;j < n;j++){ if(Length(point[i]-point[j]) <= r*r){ flag = 0; for(int k = 0;k < n; k++){ if(k == i || k == j) continue; if(Onsegment(point[k],point[i],point[j])){ flag = 1; break; } } if(flag == 0) dist[i][j] = dist[j][i] = 1; } } } } int inv[mod+10]; void gcd(int a,int b,int &x,int &y){ if(b == 0 ){ x = 1; y = 0; return ; } gcd(b,a%b,x,y); int y1 = y; y = x-a/b*y; x = y1; } int check[maxn]; int dfs(int u){ if(check[u]) return 0; check[u] = 1; int ans = 1; for(int i = 0;i < maxn; i++) if(dist[u][i] == 1) ans+=dfs(i); return ans; } struct Matrix{ int matrix[maxn][maxn]; void init(){ memset(matrix,0,sizeof(matrix)); } int Det(int n, int mod1){ int ans = 1; for(int i = 0;i < n;i++) for(int j = 0;j < n;j++) matrix[i][j] = (matrix[i][j]+mod1)%mod1; for(int i = 0;i < n; i++){ int p=i,x=matrix[i][i]; //寻找列主元 for(int j = i+1;j < n; j++){ if(abs(matrix[j][i]) > abs(x)){ x = matrix[j][i]; p = j; } } for(int j = i;j < n; j++) swap(matrix[p][j],matrix[i][j]); if(p != i) ans = -ans; if(ans < 0) ans+=mod1; if(matrix[i][i] == 0) return -1; ans = ans*matrix[i][i]%mod1; matrix[i][i] %= mod1; if(matrix[i][i] < 0) matrix[i][i]+=mod1; matrix[i][i] = inv[matrix[i][i]]; for(int j = i+1;j < n; j++){ if(matrix[j][i] == 0) continue; matrix[j][i] = (matrix[j][i]*matrix[i][i])%mod1; for(int k = i+1;k<n;k++){ matrix[j][k] = (matrix[j][k]-matrix[i][k]*matrix[j][i])%mod1; if(matrix[j][k] < 0) matrix[j][k]+=mod1; } } } return (ans%mod1+mod1)%mod1; } }; int main(){ int n,t,r,x,y; Matrix mat; for(int i = 1;i < mod;i++){ gcd(i,mod,x,y); inv[i] = (x%mod+mod)%mod; } scanf("%d",&t); while(t--){ scanf("%d%d",&n,&r); for(int i = 0;i < n; i++) scanf("%d%d",&point[i].x,&point[i].y); getDist(n,r); memset(check,0,sizeof(check)); if(dfs(0) != n){ printf("-1\n"); continue; } mat.init(); for(int i = 0;i < n; i++) for(int j = 0;j < n; j++){ if(dist[i][j] == 1){ mat.matrix[i][j] = -1; mat.matrix[i][i]++; } } int ans = mat.Det(n-1,mod); printf("%d\n",ans); } return 0; }