10307 Trees and Numbers
1.题意:
一个Case表示森林,森林有一棵至多棵树不等,每一棵树代表着一个素数,而森林代表着所有数经过某种结合产生的一个值 N。如果我给这森林加一个根成为一棵树,那么这个根节点表示的就是第N个素数,具体点来说:
2 是第一个素数,我们用一个节点表示它,在这个节点之上我再加一个节点,由于前面这个节点表示的N为2,所以新加的这个节点表示第 2 个素数即 3,在表示 3 的这个节点之上我再加一个新的节点那么就表示第 3 个素数即 5,在 5 之上再加一个新的节点,那么这时表示的是第 5 个素数即 11,不再增加节点的话,那么这棵树就表示一个值 11。
如果森林有两棵以上的数,那么这个森林表示的值 M 为各棵树表示的值相乘得到的结果。这时如果往森林里增加新节点表示为根将所有的树连接成一棵树,那么这个新节点表示的值为第 M 个素数,整棵新树表示的值同样也为第 M 个素数
2.解题思路:
首先,筛素数。根据题目给出的范围,筛出50000以为的素数,存储在数组Prime中,最好根据题目的要求将下标定为第几个素数,比如说 Prime[1] = 2, Prime[2] = 3;
然后,建树。根据题目输入的形式,可以用一个数组Parent存储 i 的双亲节点的“数组下标地址”为Parent[i], 考虑到孩子数目的不确定数,声明结构体,用孩子链表存储孩子节点,并且每个节点都要声明一个变量存储其表示的素数(具体声明可以看《数据结构》(严慧敏版)136页);
最后,遍历计算。首先要找到树根,如果数不止一棵的话,那么这片森林所代表的值为所有的树的值相乘得到的值,至于计算每棵树表示的值,采用深度优先遍历即可
Description
Can you find the rule of these equations? Let me explain for you. There are only 3 definitions: Every Tree represent a prime integer (prime integer is an integer that can only divide by 1 and itself. e.g. 2,3,5,7 etc.). A forest (one or more trees) represents a integer which is the product of trees. If we add a root for a forest (Let n to be the integer it represent) to build a tree, then this new tree represent the n-th prime integer. For example , 2 is the first prime integer , we use one node to represent it , and 3 is the second , so we add a root to 2 , it become 3. Then add a root to 3 , we get the third prime ——5. If we add a root to 5? We get the fifth prime, which is 11. Also, while combine 3 and 5 , we will get 15 since 15=3*5 . That is why 11 and 15 represent that in the figure.
Figure 2: 15=3*5 and 23 is the 9-th prime integer. Now, give you a tree, can you find the integer it represents?
输入格式
The Input will contain multiple cases. The first line contains an integer T, the number of test cases. Then T cases follow. The first line of each case, is a integer n(n>0) , that represents the number of nodes in the forest. After that, there will be one line contains n integers. The i-th integer ai means that the father node of the i-th node is ai (0<=ai<=n) . And if ai=0, it just means that i-th node is a root of tree (0 is not a node). You can assume that all this can exactly build a forest, and cases like: 2 2 1 is invalid and will not appear.
输出格式
For each case, output the answer in one line. You may assume that all the answers are less than 50000.
输入样例
7 1 0 4 0 1 2 3 5 0 1 0 3 4 5 0 1 1 1 2 6 0 0 0 3 4 4 7 0 0 5 2 2 4 1 6 0 1 1 1 1 1
输出样例
2 11 15 37 68 69 131
提示
The 2-7th sample is in the figure 1.
作者
admin
1 #include<stdio.h> 2 #include<string.h> 3 #include<malloc.h> 4 #define MAXN 50000 5 #define MAX_N 5200 6 7 typedef struct child{ 8 //孩子节点 9 int ads; //此节点的下标 10 struct child *nextchild; //指向其兄弟 11 }child; 12 13 typedef struct Tree{ 14 int num, value; //num 表示其孩子的个数,value 表示这棵树表示的素数值 15 struct child *firstchild; //指向其第一个孩子节点 16 }Tree; 17 18 typedef struct forest{ 19 int num; //只是表示这片森林一共有几个节点,这个结构体可以省略 20 Tree note[MAX_N]; 21 }forest; 22 23 forest equation; 24 int prime[MAXN/2], parent[MAXN+2]; 25 26 int store_prime() 27 {//筛出 50000 以内的素数存储到prime数组中,返回素数的个数 28 int i, j, cnt = 1; 29 memset(prime, 0, sizeof(prime)); 30 memset(parent, 0, sizeof(parent)); 31 parent[0] = parent[1] = 1; 32 for(i=2; i<MAXN+2; ++i) 33 { 34 if(!parent[i]) 35 { 36 prime[cnt++] = i; 37 for(j=i; j<MAXN+2; j += i) 38 parent[j] = 1; 39 } 40 } 41 return cnt; 42 } 43 44 void init_equation() 45 {//初始化所有的节点 46 int i; 47 for(i=1; i<=equation.num; ++i) 48 { 49 equation.note[i].num = 0; 50 equation.note[i].value = 2; 51 equation.note[i].firstchild = NULL; 52 } 53 return; 54 } 55 56 void insert(int cur, int elem) 57 {//将节点 elem 插入到其双亲节点 cur 的孩子链表中 58 int i, n; 59 child *str = NULL, *stp = NULL; 60 n = equation.note[cur].num; 61 stp = str = equation.note[cur].firstchild; 62 for(i=1; i<n; ++i) 63 stp = stp->nextchild; 64 str = (child *)malloc(sizeof(child)); 65 str->nextchild = NULL, str->ads = elem; 66 if(n == 0) equation.note[cur].firstchild = str; 67 else stp->nextchild = str; 68 ++equation.note[cur].num; 69 return; 70 } 71 /* 72 void Print(int n) 73 {//中间打印的测试函数,忽略 ~~ 74 int i, j, temp; 75 child *str = NULL; 76 for(i=1; i<=n; ++i) 77 { 78 printf("%d [%d] ", parent[i], i); 79 temp = equation.note[i].num; 80 str = equation.note[i].firstchild; 81 if(temp != 0 ) 82 do 83 { 84 printf("%d ", str->ads); 85 str = str->nextchild; 86 }while(--temp); 87 printf("\n"); 88 } 89 } 90 */ 91 92 int Traverse(int cur) 93 {//典型的深度查找,计算一棵树所代表的的素数值 94 int i, j, n, temp, k; 95 child *str = equation.note[cur].firstchild; 96 n = equation.note[cur].num; 97 if(str == NULL) return equation.note[cur].value; 98 for(i=1, k=1; i<=n; ++i) 99 { 100 k *= Traverse(str->ads); 101 str = str->nextchild; 102 } 103 return equation.note[cur].value = prime[k]; 104 } 105 106 int main() 107 { 108 // freopen("input.txt", "r", stdin); 109 int i, j, t, T, n, point, k, flag, sum, num; 110 num = store_prime(); 111 scanf("%d", &T); 112 while(T--) 113 { 114 scanf("%d", &n); 115 equation.num = n; 116 sum = 1; 117 init_equation(); 118 for(i=1; i<=n; ++i) 119 {//parent数组存储指向 i 节点的 双亲的地址下标 120 scanf("%d", &parent[i]); 121 if((point = parent[i]) != 0) 122 insert(point, i); 123 } 124 for(i=1; i<=n; ++i) 125 { 126 if(parent[i] == 0) 127 { 128 Traverse(i); 129 sum *= equation.note[i].value; 130 } 131 } 132 printf("%d\n", sum); 133 } 134 return 0; 135 }