bzoj 4401 塊的計數 思想+模擬+貪心
阿新 • • 發佈:2018-01-01
sqrt discus == 操作 興趣 貪心 input bsp 找到
Submit: 455 Solved: 261
[Submit][Status][Discuss]
1 2
2 3
2 4
4 5
5 6
塊的計數
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 455 Solved: 261
[Submit][Status][Discuss]
Description
小Y最近從同學那裏聽說了一個十分牛B的高級數據結構——塊狀樹。聽說這種數據結構能在sqrt(N)的時間內維護樹上的各種信息,十分的高效。當然,無聊的小Y對這種事情毫無興趣,只是對把樹分塊這個操作感到十分好奇。他想,假如能把一棵樹分成幾塊,使得每個塊中的點數都相同該有多優美啊!小Y很想知道,能有幾種分割方法使得一棵樹變得優美。小Y每次會畫出一棵樹,但由於手速太快,有時候小Y畫出來的樹會異常地龐大,令小Y感到十分的苦惱。但是小Y實在是太想知道答案了,於是他找到了你,一個天才的程序員,來幫助他完成這件事。
Input
第一行一個正整數N,表示這棵樹的結點總數,接下來N-1行,每行兩個數字X,Y表示編號為X的結點與編號為Y的結點相連。結點編號的範圍為1-N且編號兩兩不同。
Output
一行一個整數Ans,表示所求的方案數。
Sample Input
61 2
2 3
2 4
4 5
5 6
Sample Output
3HINT
100%的數據滿足N<=1000000。
Source
首先隨便選一個根進行dfs得到size[x]表示以x為根節點的子樹的大小。然後我們假設答案為t,需要判斷t是否可行。首先顯然需要t|n。
顯然每一個塊有且僅有一個根,定義為這個塊的最高點。然後我們發現一個點x是塊的根的必要條件是t|size[x]!這個是顯然的。然後我
們統計有多少個size[x]被t整除,如果與n/t相同則合法,否則一定小於n/t,因此一定不合法。
1 #include<cstring> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdio> 6 7 #define N 1000007 8 #define ll long long 910 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘)f=-1;ch=getchar();} 15 while (ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 16 return x*f; 17 } 18 19 int n,ans; 20 int Head[N],ret[N<<1],Next[N<<1],tot; 21 int size[N],st[N]; 22 23 inline void ins(int u,int v) 24 { 25 ret[++tot]=v; 26 Next[tot]=Head[u]; 27 Head[u]=tot; 28 } 29 void dfs(int u,int f) 30 { 31 size[u]=1; 32 for (int i=Head[u];i;i=Next[i]) 33 { 34 if (ret[i]==f) continue; 35 dfs(ret[i],u); 36 size[u]+=size[ret[i]]; 37 } 38 st[size[u]]++; 39 } 40 int main() 41 { 42 n=read(); 43 for (int i=1;i<n;i++) 44 { 45 int u=read(),v=read(); 46 ins(u,v);ins(v,u); 47 } 48 dfs(1,0); 49 for (int i=1;i<=n;i++) 50 if (n%i==0) 51 { 52 int sum=0; 53 for (int j=i;j<=n;j+=i) 54 sum+=st[j]; 55 if (sum==n/i) ans++; 56 } 57 printf("%d\n",ans); 58 }
bzoj 4401 塊的計數 思想+模擬+貪心