bzoj4401 块的计数 乱搞

版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/82737180

Description


小Y最近从同学那里听说了一个十分牛B的高级数据结构——块状树。听说这种数据结构能在sqrt(N)的时间内维护树上的各种信息,十分的高效。当然,无聊的小Y对这种事情毫无兴趣,只是对把树分块这个操作感到十分好奇。他想,假如能把一棵树分成几块,使得每个块中的点数都相同该有多优美啊!小Y很想知道,能有几种分割方法使得一棵树变得优美。小Y每次会画出一棵树,但由于手速太快,有时候小Y画出来的树会异常地庞大,令小Y感到十分的苦恼。但是小Y实在是太想知道答案了,于是他找到了你,一个天才的程序员,来帮助他完成这件事。

100%的数据满足N<=1000000。

Solution


很有意思的水题

考虑枚举答案x,我们发现x一定是n的约数,并且一定有n/x个节点的size是x的倍数
注意到我们可以开一个桶然后枚举答案的倍数计数,这样就是nlogn的了

Code


#include <stdio.h>
#include <string.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)

const int N=1000005;

struct edge {int y,next;} e[N*2];

int size[N],ls[N],rec[N],edCnt,n;

int read() {
    int x=0,v=1; char ch=getchar();
    for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
    for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
    return x*v;
}

void add_edge(int x,int y) {
    e[++edCnt]=(edge) {y,ls[x]}; ls[x]=edCnt;
    e[++edCnt]=(edge) {x,ls[y]}; ls[y]=edCnt;
}

void dfs(int now,int fa) {
    size[now]=1;
    for (int i=ls[now];i;i=e[i].next) {
        if (e[i].y!=fa) {
            dfs(e[i].y,now); size[now]+=size[e[i].y];
        }
    }
    rec[size[now]]++;
}

int calc(int x) {
    int cnt=0;
    for (int i=x;i<=n;i+=x) {
        cnt+=rec[i];
    }
    return (cnt==n/x);
}

int main(void) {
    n=read(); int ans=0;
    rep(i,2,n) add_edge(read(),read());
    dfs(1,0);
    for (int i=1;i*i<=n;++i) if (n%i==0) {
        ans+=calc(i)+calc(n/i)*(i*i!=n);
    }
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/82737180