• SCAU 2011 校赛 10307 Trees and Numbers


    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 }
    物役记

    更多内容请关注个人微信公众号 物役记 (微信号:materialchains)

  • 相关阅读:
    [ZJOI2010]count 数字计数
    小雄数
    简单筛法函数
    [Noip模拟题]lucky
    欧拉线筛
    Intern Day78
    CodeForces1360C
    CodeForces1373B
    Intern Day78
    Intern Day78
  • 原文地址:https://www.cnblogs.com/liaoguifa/p/3027041.html
Copyright © 2020-2023  润新知