• Bzoj3004 吊灯


    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 72  Solved: 46

    Description

           Alice家里有一盏很大的吊灯。所谓吊灯,就是由很多个灯泡组成。只有一个灯泡是挂在天花板上的,剩下的灯泡都是挂在其他的灯泡上的。也就是说,整个吊灯实际上类似于一棵树。其中编号为1的灯泡是挂在天花板上的,剩下的灯泡都是挂在编号小于自己的灯泡上的。
           现在,Alice想要办一场派对,她想改造一下这盏吊灯,将灯泡换成不同的颜色。她希望相同颜色的灯泡都是相连的,并且每一种颜色的灯泡个数都是相同的。
           Alice希望你能告诉她,总共有哪些方案呢?
           Alice是一个贪心的孩子,如果她发现方案不够多,或者太多了,就会很不高兴,于是她会尝试调整。对于编号为x(x≠1)的灯泡,如果原来是挂在编号为f[x]的灯泡上,那么Alice会把第x个灯泡挂到第 ( f[x] + 19940105 ) mod (x-1) + 1 个灯泡上。
           由于九在古汉语中表示极大的数,于是,Alice决定只调整9次。对于原始状态和每一次调整过的状态,Alice希望你依次告诉她每种状态下有哪些方案。

    Input

           第一行一个整数n,表示灯泡的数量。
           接下来一行,有n-1个整数Ui,第i个数字表示第i+1个灯泡挂在了Ui个的下面。保证编号为1的灯泡是挂在天花板上的。数字之间用逗号‘,’隔开且最后一个数字后面没有逗号。

    Output

           对于10种状态下的方案,需要按照顺序依次输出。
    对于每一种状态,需要先输出单独的一行,表示状态编号,如样例所示。
    之后若干行,每行1个整数,表示划分方案中每种颜色的灯泡个数。
           按升序输出。
     

    Sample Input

    6
    1,2,3,4,5

    Sample Output

    Case #1:
    1
    2
    3
    6
    Case #2:
    1
    2
    6
    Case #3:
    1
    3
    6
    Case #4:
    1
    3
    6
    Case #5:
    1
    3
    6
    Case #6:
    1
    2
    6
    Case #7:
    1
    2
    3
    6
    Case #8:
    1
    6
    Case #9:
    1
    2
    6
    Case #10:
    1
    3
    6

    HINT

           对于100%的数据,n<=1.2*106。

    Source

    脑洞题。

    看到数据范围,内心惴惴不安。再看时间限制10s,嗨呀,随便写嘛!

    树的重建是需要暴力维护的,不可避。

    重建树后,统计每个结点的子树的结点总数。如果每种颜色的灯泡有k个,那么必须满足n%k==0,且结点数等于k的倍数的子树有n/k个。

    统计树size的时候,建边DFS太浪费时间,由于每个结点的父亲编号必定小于自身,可以从编号n到编号1依次上传更新size。

     1 /*by SilverN*/
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 using namespace std;
     8 const int mxn=1200010;
     9 int read(){
    10     int x=0,f=1;char ch=getchar();
    11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 int n;
    16 int a[mxn],cnt=0;
    17 int fa[mxn],num[mxn];
    18 int c[mxn];
    19 //void DFS(int u,int fa){
    20 //}
    21 void reset(){
    22     for(int i=2;i<=n;i++){
    23         fa[i]=(fa[i]+19940105)%(i-1)+1;
    24     }
    25     return;
    26 }
    27 void init1(){
    28     int m=sqrt(n);
    29     for(int i=1;i<=m;i++){
    30         if(n%i==0){
    31             a[++cnt]=i;
    32             if(i*i!=n)a[++cnt]=n/i;
    33         }
    34     }
    35     return;
    36 }
    37 void init(){
    38     memset(c,0,sizeof c);
    39     for(int i=1;i<=n;i++)num[i]=1;
    40     return;
    41 }
    42 void solve(){
    43     init();
    44     int i,j;
    45     for(i=n;i>=1;i--)
    46         num[fa[i]]+=num[i];
    47     for(i=1;i<=n;i++)c[num[i]]++;
    48     for(i=1;i<=cnt;i++){
    49         int x=a[i];//每种颜色x个灯泡
    50         int res=0;
    51         for(j=x;j<=n;j+=x){
    52             res+=c[j];
    53         }
    54         if(n/x==res)printf("%d
    ",x);
    55     }
    56     return;
    57 }
    58 int main(){
    59     n=read();
    60     init1();
    61     int i,j;
    62     for(i=2;i<=n;i++)fa[i]=read();
    63     printf("Case #1:
    ");
    64     solve();
    65     for(i=1;i<=9;i++){
    66         printf("Case #%d:
    ",i+1);
    67         reset();
    68         solve();
    69     }
    70     return 0;
    71 }
  • 相关阅读:
    架构设计的方法学 【转】
    异常处理
    Java中---HashSet中的Set()方法不能加重复值的原因,唯一性
    java中Set集合
    java中foreach语法和总结
    泛型的处理
    迭代器错误处理
    防重复提交
    mqtt安装和使用
    字符串正则替换
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6189105.html
Copyright © 2020-2023  润新知