码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 1034C Region Separation - 数论 - 动态规划

时间:2018-09-24 12:44:22      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:==   accept   div   ted   type   第一部分   text   eth   构造   

题目传送门

  传送站I

  传送站II

  传送站III

题目大意

  给定一个$n$个点的树$T = (G, V)$,每个点有一个正整数点权$a_{i}$。整棵树是第1级划分。定义第$i$级划分是将第$i - 1$级划分中的每个区域划分成至少两个新的区域,并且所有区域都是一个连通块,每个点在每一级中只属于一个区域,在同一级划分内每个区域内的点的点权和相等。一种划分方案包含它划分的每一级。两种划分方案不同当且仅当它们划分的级数不同,或者存在一个点在某一级中它们在两种划分方案中属于不同区域。

  之前好像某次noip模拟考过类似的东西,但是当时没弄得清楚,感性理解了这个东西qwq。题解里涉及的大部分结论都被我猜到了,证这些花了半天,最后弃疗看题解。(为啥做了三道计数题都看了题解,果然我太菜了。)

注意

  以下结论都在这样一些限制条件下讨论:

  1. 点权均为正整数。
  2. 每个点只属于一个区域。
  3. 如果涉及到有根树相关,默认以1为根。

  设$s_{i}$表示以1为根时子树$i$内的点权和,$S = s_{1}$。

引理1 一棵$n$个点数的树,设$S = kS‘, k\in N_{+}, S‘ \in N$,则$\sum_{i = 1}^{n} [S‘\mid s_{i}] \leqslant k$

  证明 当$k = 1$的时候,因为$a_{1} > 0$,所以它的子树内的所有点的$s_{i} < k$。

  假设当$k \leqslant m - 1$时成立,考虑$k = m$的时候

  • 若树内不存在一个点$i$,使得$s_{i} = xS‘, x \in N\wedge 1\leqslant x < m$,则$\sum_{i = 1}^{n} [S‘\mid s_{i}] = 1$,显然成立。
  • 若树内存在一个点$i$,使得$s_{i} = xS‘, x \in N\wedge 1\leqslant x < m$,那么我们将它和它的父节点的边断开,把树分成两半部分,一半部分和为$xS‘$,另一部分和为$(m - x)S‘$。对于第一部分,它一定是以1为根的时候完整的一棵子树,把它删去后$i$的祖先的$s$值会减少,但是因为$S‘\mid s_{i}$,所以不会改变祖先的$s_{i}$对$S‘$取模后的剩余。因此可以将第一部分看成以$i$为根的树,第二部分看成以$1$为根的树,根据归纳假设易知,$\sum_{i = 1}^{n} [S‘\mid s_{i}] \leqslant m$。

  所以定理得证。

  不难发现,当$S‘$不是整数的时候,$\sum_{i = 1}^{n} [\frac{S‘}{s_{i}}\in Z] \leqslant k$也成立。因为我们将每个点的点权乘上$k$,这样新的$S‘$就是整数了,用引理1可得:

$\sum_{i = 1}^{n} [\frac{S‘}{s_{i}}\in Z] = \sum_{i = 1}^{n}[\frac{kS‘}{ks_{i}}\in Z]=\sum_{i = 1}^{n}[kS‘\mid ks_{i}]\leqslant k$

  对于一个树$T = (V, E)$,设$f(T, d) = \sum_{v_{i} \in V} [d\mid s_{v_{i}}]$。

定理2 一棵$n$个点数的树$T$,能将它划分成$k$个点权和相等的连通块的充分必要条件是:

  1. $k\mid S$
  2. $f(T, \frac{S}{k}) = k$

  证明 第一点的必要性显然,现在只考虑第二点。设$S = kS‘$。

  必要性 我们考虑$k$个连通块,每个连通块的最浅点的$s$值一定是$S‘$的倍数。因为假设它不是$S‘$的倍数,那么由第一点的必要性可知它的子树内不能划分成若干联通块,剩下的点会被孤立,这样会使得划分方式不合法。

  充分性 我们将所有满足$S‘ \mid s_{i}, i > 1$的点都和它的父节点把边断开,显然会产生$k$个连通块,现在证明这样一定满足条件:

    1. 因为点的权值都为正,所以不存在一个连通块的和为0或负数。
    2. 显然每个连通块的点权都是$S‘$的倍数
    3. 假设存在一个连通块的点权大于$S‘$,那么把它删去后会剩下若干个树$T_{1}, \cdots, T_{p}$,它们的点权和小于$(k - 1)S‘$,由引理1易证$\sum_{i = 1}^{p}f(T_{i}, S‘) < k - 1$。所以这个连通块内至少存在两个点它们的$s$值是$S‘$的倍数,这与构造的方案矛盾。所以不存在一个连通块的权值和大于$S‘$。

  由以上三点可知对于每一个连通块的权值都是$S‘$。因此定理得证。

  同时我们由证明过程也知道,满足$S‘ \mid s_{i}, i > 1$的点都必须和它的父节点把边断开,也就是说方案是唯一的。

  也就是说:

推论3 一棵$n$个点数的树$T$,能将它划分成$k$个点权和相等的连通块的方案数要么是0,要么是1。

  先考虑对于第2级划分,我们希望知道对于每一个$k, 1\leqslant k \leqslant n$,$f(T, \frac{S}{k})$的值。

  根据定义有

$f(T, \frac{S}{k}) = \sum_{v_{i} \in V} [\frac{S}{k}\mid s_{v_{i}}]\\= \sum_{v_{i} \in V} [S\mid s_{v_{i}}k]\\= \sum_{v_{i} \in V} [\frac{S}{(S, s_{i})}\mid k]$

  那么现在可以用一个简单dp在$O(n\log n)$内处理掉它。

  考虑级数大于2的时候,不难发现以下结论:

定理4 一棵$n$个点数的树$T$,能够划分成2个分别包含$k_{1}, k_{2}\ \ (k_{1} < k_{2})$个区域的级别的充分必要条件是:

  1. $k_{1}\mid k_{2}, k_{2}\mid S$
  2. $f(T, \frac{S}{k_1}) = k_1 \wedge f(T, \frac{S}{k_2}) = k_2$

  证明 必要性显然。

  充分性 考虑我们将这个数划分成$k_{1}$个区域,每个区域是一个连通块,那么就是一棵树。设它们分别是$T_{1}, \cdots, T_{k_{1}}$。每一部分的和都是$\frac{S}{k_{1}}$,由第一点可知是$\frac{S}{k_{2}}$的倍数,因此分开后对$s_{i}$对$\frac{S}{k_{2}}$取模后的剩余无影响。由引理1可知$f(T_{i}, \frac{S}{k_{2}}) \leqslant \frac{k_2}{k_1}$,又因为$f(T, \frac{S}{k_2}) = k_2 = k_{1}\times \frac{k_{2}}{k_{1}}$,所以$f(T_{i}, \frac{S}{k_{2}}) = \frac{k_2}{k_1}$,由定理2可知每一区域都可以划分成$\frac{k_{2}}{k_{1}}$个新区域。

  因此定理得证。

  由推论3和定理4可知如果将划分成$k$个区域的方案看成一个点,满足$k_{1}, k_{2}\ \ (k_{1} < k_{2})$和定理4的两点的两个合法的一级划分,那么$k_{1}$向$k_{2}$连一条有向边,显然它构成了一个DAG。那么一个合法的划分方案对应从1开始的一条路径。现在就简单了,用$g_{i}$表示以$i$为路径结尾的路径条数,再做一次dp就完了。

  最后来证一个可以压常数的结论,推广一下$f$,现在把它设成$f(T, d) = \sum_{v_{i} \in V} [\frac{s_{v_{i}}}{d} \in Z]$。

推论5 一棵$n$个点数的树$T$,设$S = kS‘, k\in N_{+}, k > 1, k\nmid S$,则$f(T, S‘) < k$

  证明 考虑$k = 2$的时候,因为$k\nmid S$,所以只有$s_{1}$满足条件,$f(T, S‘) = 1 < 2$。

  假设当$k \leqslant m - 1$的时候成立,考虑$k = m$的时候,

  • 若不存在一个点$i, i > 1$使得$\frac{s_{i}}{S‘} \in Z$,那么$f(T, S‘) = 1 < m$。
  • 若存在一个点$i, i > 1$使得$\frac{s_{i}}{S‘} \in Z$,那么我们把它和它的父节点的边断开,把树分成两棵树$T_{1}, T_{2}$,因为$\frac{s_{i}}{S‘}$的小数部分为0,所以对它的祖先$\frac{s_{j}}{S‘}$的小数部分没有影响,即不会改变它是否为整数。显然两部分的和都小于$mS‘$,所以由归纳假设可知当$k = m$时成立。

  因此定理得证。

  现在就不用判断$k$是否是$S$的约数了,只用判断$f(T, \frac{S}{k})$的值。

  总时间复杂度$O(n\log n)$。

Code

 1 /**
 2  * Codeforces
 3  * Problem#1034C
 4  * Accepted
 5  * Time: 717ms
 6  * Memory: 19900k
 7  */
 8 #include <bits/stdc++.h>
 9 #ifndef WIN32
10 #define Auto "%lld"
11 #else
12 #define Auto "%I64d"
13 #endif
14 using namespace std;
15 typedef bool boolean;
16 #define ll long long
17 
18 const int N = 1e6 + 5, M = 1e9 + 7;
19 
20 ll gcd(ll a, ll b) {
21     return (b) ? (gcd(b, a % b)) : (a);    
22 }
23 
24 int add(int a, int b) {
25     return ((a += b) >= M) ? (a - M) : (a);
26 }
27 
28 int n, res;
29 ll ss[N];
30 int fa[N], f[N], g[N];
31 
32 int main() {
33     scanf("%d", &n);
34     for (int i = 1; i <= n; i++)
35         scanf(Auto, ss + i);
36     for (int i = 2; i <= n; i++)
37         scanf("%d", fa + i);
38     for (int i = n; i > 1; i--)
39         ss[fa[i]] += ss[i];
40     ll S = ss[1];
41     for (int i = 1; i <= n; i++)
42         if ((ss[i] = S / gcd(S, ss[i])) <= n)
43             f[ss[i]]++;
44     for (int i = n; i; i--)
45         for (int j = i << 1; j <= n; j += i)
46             f[j] += f[i];
47     g[1] = 1;
48     for (int i = 1; i <= n; i++)
49         if (f[i] == i) {
50             res = add(res, g[i]);
51             for (int j = i << 1; j <= n; j += i)
52                 g[j] = add(g[j], g[i]);
53         }
54     printf("%d\n", res);
55     return 0;
56 }

Codeforces 1034C Region Separation - 数论 - 动态规划

标签:==   accept   div   ted   type   第一部分   text   eth   构造   

原文地址:https://www.cnblogs.com/yyf0309/p/9694235.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!