[SDOi2012]吊灯
嘟嘟嘟
这题想了半天,搞出了一个\(O(10 * d * n)\)(\(d\)为\(n\)的约数个数)的贪心算法,就是能在子树内匹配就在子树内匹配,否则把没匹配的都交给父亲,看父亲能否匹配。交上去开了O2才得了60分。按讨论中的方法卡常后还是A不了,就放弃了。
正解需要推一个结论,就是一棵树能被分成\(x\)个大小相同的联通块,必须满足至少有\(\frac{n}{x}\)个子树的大小为\(x\)的倍数。
证明啥的yy一下就好啦……
想到这个结论后,我还是没想出复杂度更优的算法……最后看题解才知道,你开个桶记录子树大小,每次枚举倍数就能把\(n\)降成\(\sqrt{n}\)了……
啊忘说了,讨论中的卡常就是根据题中树的构造方法,把dfs改成逆序扫一遍,减小常数。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1.2e6 + 5;
const int NUM = 19940105;
inline ll read()
{
  ll ans = 0;
  char ch = getchar(), last = ' ';
  while(!isdigit(ch)) last = ch, ch = getchar();
  while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  if(last == '-') ans = -ans;
  return ans;
}
inline void write(ll x)
{
  if(x < 0) x = -x, putchar('-');
  if(x >= 10) write(x / 10);
  putchar(x % 10 + '0');
}
int n, fa[maxn];
struct Edge
{
  int nxt, to;
}e[maxn];
int head[maxn], ecnt = -1;
In void addEdge(int x, int y)
{
  e[++ecnt] = (Edge){head[x], y};
  head[x] = ecnt;
}
int num[maxn], cnt = 0;
In void init(int n)
{
  for(int i = 1; i * i <= n; ++i)
    if(n % i == 0)
      {
	num[++cnt] = i;
	if(i * i < n) num[++cnt] = n / i;
      }
  sort(num + 1, num + cnt + 1);
}
int ans;
int dp[maxn];
In bool dfs(int now, int _f)  //我的O(n)贪心
{
  for(int i = 1; i <= n; ++i) dp[i] = 1;
  for(int i = n; i; --i)
    {
      if(dp[i] > ans) return 0;
      if(dp[i] == ans) dp[i] = 0;
      dp[fa[i]] += dp[i];
    }
  return 1;
}
int siz[maxn], tot[maxn];
In bool judge(int x)
{
  int ret = 0;
  for(int i = x; i <= n; i += x) ret += tot[i];
  return ret >= n / x;
}
In void solve()
{
  fill(siz + 1, siz + n + 1, 1);
  fill(tot + 1, tot + n + 1, 0);
  for(int i = n; i; --i)
    {
      siz[fa[i]] += siz[i];
      ++tot[siz[i]];
    }
  for(int i = 1; i <= cnt; ++i)
    {
      ans = num[i];
      if(judge(num[i])) write(ans), enter;
    }
}
int main()
{
  n = read(); init(n);
  for(int i = 2; i <= n; ++i) fa[i] = read();
  puts("Case #1:");
  solve();
  for(int t = 1; t <= 9; ++t)
    {
      printf("Case #%d:\n", t + 1);
      for(int i = 2; i <= n; ++i) fa[i] = (fa[i] + NUM) % (i - 1) + 1;
      solve();
    }
  return 0;
}
[SDOi2012]吊灯的更多相关文章
- P2351 [SDOi2012]吊灯
		P2351 [SDOi2012]吊灯 https://www.luogu.org/problemnew/show/P2351 题意: 一棵树,能否全部分成大小为x的联通块. 分析: 显然x是n ... 
- [bzoj3004] [SDOi2012]吊灯
		Description Alice家里有一盏很大的吊灯.所谓吊灯,就是由很多个灯泡组成.只有一个灯泡是挂在天花板上的,剩下的灯泡都是挂在其他的灯泡上的.也就是说,整个吊灯实际上类似于[b]一棵树[/b ... 
- 洛谷P2351 [SDOi2012]吊灯  【数学】
		题目 Alice家里有一盏很大的吊灯.所谓吊灯,就是由很多个灯泡组成.只有一个灯泡是挂在天花板上的,剩下的灯泡都是挂在其他的灯泡上的.也就是说,整个吊灯实际上类似于[b]一棵树[/b].其中编号为 1 ... 
- BZOJ.3004.[SDOI2012]吊灯(结论)
		题目链接 BZOJ 洛谷 题意: 将树划分为k个连通块,要求每个连通块大小相同.输出可能的大小. 结论: 满足条件时颜色的连通块数为k,当且仅当有 \(n/k\) 个节点满足它的子树是k的倍数(显然还 ... 
- [bzoj3004][SDOI2012]吊灯——樹形DP
		Brief Description 給定一棵樹, 判斷是否可以將其分成\(\frac{n}{k}\)個聯通塊, 其中每個聯通塊的大小均爲k. Algorithm Design 我們有一個結論: k可行 ... 
- BZOJ 2705: [SDOI2012]Longge的问题 [欧拉函数]
		2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 2553 Solved: 1565[Submit][ ... 
- BZOJ 2705: [SDOI2012]Longge的问题
		2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 2554 Solved: 1566[Submit][ ... 
- Bzoj3004 吊灯
		Time Limit: 10 Sec Memory Limit: 128 MB Submit: 72 Solved: 46 Description Alice家里有一盏很大的吊灯.所 ... 
- 【BZOJ】【3004】吊灯
		思路题 要将整棵树分成大小相等的连通块,那么首先我们可以肯定的是每块大小x一定是n的约数,且恰好分成$\frac{n}{x}$块,所以我有了这样一个思路:向下深搜,如果一个节点的size=x,就把这个 ... 
随机推荐
- Java中的方法重载与方法重写
			重载(overload) 重载是在一个类中,同名方法拥有不同的参数列表则视为重载.不同的参数列表包括:参数数量不同,参数类型不同,参数顺序不同.重载对于返回类型没有要求,所以不能通过返回类型去判断是否 ... 
- 使用mybatis开发dao方法
			使用mybatis开发dao的时候, 主要涉及到SqlSessionFactoryBuilder.SqlSessionFactory.SqlSession 这三个类 现在将这三个类的使用方法简单的说下 ... 
- python网络爬虫入门(一)
			python网络爬虫(一) 2018-02-10 python版本:python 3.7.0b1 IDE:PyCharm 2016.3.2 涉及模块:requests & builtwit ... 
- [Android][Framework] 添加系统服务
			新博客地址 http://wossoneri.github.io/2018/09/15/[Android][Framework]create-system-service/ 做系统开发,有时候需要自己 ... 
- PhpStorm和WAMP配置调试参数,问题描述Error. Interpreter is not specified or invalid. Press “Fix” to edit your project configuration.
			PhpStorm和WAMP配置调试参数,解决实际问题. 问题描述: Error. Interpreter is not specified or invalid. Press "Fix&qu ... 
- Orchard详解--第九篇  拓展模块及引用的处理
			在分析Orchard的模块加载之前,先简要说一下因为Orchard中的模块并不是都被根(启动)项目所引用的,所以当Orchard需要加载一个模块时首先需要保证该模块所依赖的其它程序集能够被找到,那么才 ... 
- redis sentinel集群的搭建
			背景说明: 这里采用1主2从的redis集群,3个sentinel搭建高可用redis集群. 一,关于搭建redis-sentinel高可用之前,我们必须要了解redis主从搭建redis-senti ... 
- linux vbundle插件配置
			1.新建目录,clone源码 mkdir ~/.vim/bundle/ git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vun ... 
- CentOS7中安装MySQL5.7
			安装必要的组件 yum install –y autoconf automake imake libxml2-devel expat-devel cmake gcc gcc-c++ libaio li ... 
- 洗礼灵魂,修炼python(80)--全栈项目实战篇(8)—— 计算器
			用正则表达式开发一个计算器,计算用户给定的一串带有加减乘除的公式. 要求:不能使用eval转换字符串 分析: 要求简单,就是计算混合运算,但是不能使用eval直接转换,主要就是把整个式子中的小括号优先 ... 
