KIDx的解题报告
题意:给出n个点,给出R,两点距离不大于R而且两点之间没其他点阻碍,就可以建一条边,问可以形成多少棵生成树,如果没有,输出-1,否则,输出(生成树个数 mod 10007)
典型的生成树计数:
①求出邻接矩阵G
②求出度数矩阵D
③D-G得出Kirchhoff矩阵
④求Kirchhoff矩阵任意n-1阶子矩阵的行列式
一些概念不懂的话还是要看看周冬的《生成树的计数及其应用》http://wenku.baidu.com/view/782ab9eb19e8b8f67c1cb9a9.html
当然取余方面要用到逆元的知识:
乘法逆元:
x*y ≡ 1mod (mod),则称 x 是 y 对于mod的乘法逆元
分数取模就要用到了,如求(a/b) % mod = ?
那就要先解决b^-1 % mod = ?
就等价于b的逆元x%mod了,求出x即可变为求a*x % mod = ?
令y = b,x*y ≡ 1mod (mod) → x*y + k*mod == 1
用扩展欧几里德即可算出y的逆元x
#include <iostream>
using namespace std;
#define M 305
struct point{
int x, y;
}p[M];
int C[M][M], G[M][M];
int mod = 10007;
int dis (point a, point b)
{
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}
void Egcd (int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1, y = 0;
return ;
}
Egcd (b, a%b, x, y);
int tp = x;
x = y;
y = tp - a/b*y;
}
int det (int n) //计算n阶行列式
{
int i, j, k, ans = 1, x, y, flg = 1;
for (i = 0; i < n; i++)
{
if (C[i][i] == 0)
{
for (j = i+1; j < n; j++)
if (C[j][i])
break;
if (j == n) return -1;
flg = !flg;
for (k = i; k < n; k++)
swap (C[i][k], C[j][k]);
}
ans = ans * C[i][i] % mod;
Egcd (C[i][i], mod, x, y);
x = (x%mod + mod) % mod; //注意保证取余结果为最小非负数
for (k = i+1; k < n; k++)
C[i][k] = C[i][k] * x % mod;
for (j = i+1; j < n; j++)
if (C[j][i] != 0) for (k = i+1; k < n; k++)
C[j][k] = ((C[j][k] - C[i][k]*C[j][i])%mod + mod) % mod;
//注意保证取余结果为最小非负数
}
if (flg) return ans;
return mod-ans;
}
int main ()
{
int i, j, k, t, n, r;
scanf ("%d", &t);
while (t--)
{
scanf ("%d%d", &n, &r);
for (i = 0; i < n; i++)
scanf ("%d%d", &p[i].x, &p[i].y);
memset (G, 0, sizeof(G));
for (i = 0; i < n; i++) //建图
{
for (j = i + 1; j < n; j++)
{
int tp = dis (p[i], p[j]);
if (tp > r*r) continue;
for (k = 0; k < n; k++)
{
if (k == i || k == j) continue;
if ((p[i].x-p[k].x)*(p[j].y-p[k].y) ==
(p[j].x-p[k].x)*(p[i].y-p[k].y) &&
dis (p[i], p[k]) < tp && dis (p[j], p[k]) < tp)
break;
}
if (k == n) G[i][j] = G[j][i] = 1;
}
}
memset (C, 0, sizeof(C));
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
if (G[i][j])
++C[i][i], ++C[j][j];
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
{
C[i][j] -= G[i][j];
C[i][j] = (C[i][j]%mod + mod) % mod;
//注意保证取余结果为最小非负数
}
printf ("%d\n", det(n-1));
}
return 0;
}
分享到:
相关推荐
(HDUACM2010版_06)并查集(最小生成树(HDUACM2010版_06)并查集(最小生成树(HDUACM2010版_06)并查集(最小生成树(HDUACM2010版_06)并查集(最小生成树
杭电ACM课件2014版之 (HDUACM201403版_06)并查集(最小生成树)
总结来说,"二叉搜索树练习 HDU3791"是一道关于二叉搜索树操作的编程题,可能需要实现插入、删除、查找等基本操作,并通过分析`Main.java`源码来理解和解决问题。同时,可能需要借助各种工具进行调试和测试,以确保...
HDUACM201509版_07并查集(最小生成树).ppt文件很可能包含了关于这个问题的详细讲解,包括并查集的建立、维护以及如何与Kruskal算法结合来求解最小生成树的问题。 并查集是一种用于处理连接关系的数据结构,它可以...
2. **生成树配置**:1.3.5 生成树的配置.docx - 生成树协议(如STP、RSTP或MSTP)用于防止局域网中的环路,确保数据包只沿着唯一的路径转发,避免数据丢失和循环。实验可能涵盖了生成树的配置、状态监控和故障排除...
3. **数据结构**:数组、链表、栈、队列、树(二叉树、平衡树如AVL和红黑树)、图(邻接矩阵、邻接表、最小生成树、拓扑排序等)。 4. **字符串处理**:KMP算法、Manacher's Algorithm、Rabin-Karp算法等。 5. **...
hdu 1166线段树代码
8. **图论与树**:HDU题目中可能涉及图的遍历(深度优先搜索DFS、广度优先搜索BFS)、树的遍历(前序、中序、后序)以及最小生成树、最短路径等算法。 9. **动态规划**:这是一种优化策略,通过构建状态转移方程来...
本分类涵盖了图论领域的多种类型的题目,涉及到图论的基本概念、图的遍历、图的搜索、图的匹配、图的.isConnected性、图的最短路径、图的最小生成树、图的拓扑排序等多个方面。 图论是一个重要的计算机科学领域,...
【标题】"HDU_2010.rar"是一个压缩包文件,其中包含了与"HDU 2010"相关的资源,特别是针对"HDU ACM20"比赛的编程题目。"hdu 2010"和"hdu 20"可能是该比赛的不同简称或分类,而"hdu acm20"可能指的是该赛事的第20届...
在ACM(国际大学生程序设计竞赛)中,HDU(杭州电子科技大学)的在线判题系统是许多参赛者磨炼算法技巧的重要平台。这个平台涵盖了众多的算法问题,旨在提升参赛者的编程能力和逻辑思维能力。以下是对标题和描述中...
1. **基础算法**:包括排序(快速排序、归并排序等)、搜索(二分查找、深度优先搜索等)、图论(最短路径、最小生成树等)。 2. **动态规划**:解决许多具有重叠子问题和最优子结构的问题,如背包问题、最长公共子...
4. **图论算法**:最短路径算法(Dijkstra、Floyd-Warshall)、拓扑排序、最小生成树(Prim、Kruskal)等。 5. **数学方法**:模运算、数论、组合数学等。 6. **字符串处理**:KMP匹配、Z算法、后缀数组、AC自动机等...
ACM HDU 题目分类 ACM HDU 题目分类是指对 HDU 在线判题系统中题目的分类,总结了大约十来个分类。这些分类将有助于编程选手更好地理解和解决问题。 DP 问题 DP(Dynamic Programming,动态规划)是一种非常重要...
1. **基础算法**:包括排序算法(快速排序、归并排序、堆排序等)、搜索算法(深度优先搜索、广度优先搜索、A*搜索等)、图论算法(最短路径、最小生成树、拓扑排序等)和动态规划等。 2. **数据结构**:如链表、...
### hdu1250高精度加法 #### 背景介绍 在计算机科学与编程竞赛中,处理大整数运算(特别是加法、减法、乘法等)是常见的需求之一。当数字的位数超过了标准数据类型(如`int`、`long`等)所能表示的最大值时,就需要...
【标题】"HDU DP动态规划"涉及到的是在算法领域中的动态规划(Dynamic Programming,简称DP)技术,这是解决复杂问题的一种高效方法,尤其适用于有重叠子问题和最优子结构的问题。动态规划通常用于优化多阶段决策...
HDU1059的代码
hdu1001解题报告
hdu 1574 passed sorce