@description@

有n个城市,每个城市有个权值wi,任意两个城市i,j之间的道路数有wi∗wj条。

对于每种生成树,设每个点的度数为di,其权值定义为∏di。

问所有无根生成树的权值和。答案对1e9+7取模。

Class:

ConnectedStates

Method:

getSum

Parameters:

int[]

Returns:

int

Constraints

n <= 2000

Examples

0)

{"3, 10"}

Returns: 30

1)

{"2, 2, 2"}

Returns: 96

2)

{"1, 1, 1, 1"}

Returns: 60

@solution@

考虑如果固定了生成树的形态,对应的方案应该是所有树边条数的乘积。

稍微变一变其实就是 \(\prod_{i=1}^{n}w_{i}^{d_i}\),这样就只跟点的度数有关了。

根据我们的 prufer 定理,最终答案为:

\[ans = (n-2)!*\sum_{(\sum_{i=1}^{n}d_i) = 2*n-2}(\prod_{i=1}^{n}\frac{w_{i}^{d_i}}{(d_i-1)!}*d_i)
\]

如果将 i 有关的项整理到一起然后 fft 一下的时间复杂度是 O(n^2*logn),但是我们可以做到更优。

优化的思路来源在于多项式的幂公式,即:

\[(a_1 + a_2 + ... + a_n)^k = k!*\sum_{(\sum_{i=1}^{n}b_i) = k}(\prod_{i=1}^{n}\frac{a_{i}^{b_i}}{{b_i}!})
\]

注意到下面这个公式和上面的答案表达式其实是很相像的,我们考虑进一步地变形:

令 \(a_i = d_i - 1\),得到:

\[ans = (\prod_{i=1}^{n}w_i)*(n-2)!*\sum_{(\sum_{i=1}^{n}a_i) = n-2}(\prod_{i=1}^{n}\frac{w_{i}^{a_i}}{a_i!}*(a_i+1))
\]

基本就是一样了,但还有一个 \(\prod_{i=1}^{n}(a_i + 1)\) 阻碍我们。

考虑将它拆开,依次考虑每一个单项式 \(a_{p_1}*a_{p_2}*...*a_{p_m} = \prod_{j=1}^{m}a_{p_j}\) 的贡献,其中 \(1 \le p_1 < p_2 < ... < p_m \le n\)。它的贡献为:

\[\sum_{(\sum_{i=1}^{n}a_i) = n-2}(\prod_{i=1}^{n}\frac{w_{i}^{a_i}}{a_i!}* \prod_{j=1}^{m}a_{p_j})
\]

考虑将这些 a 乘入阶乘中去,令得到的新的阶乘分别为 \(c_1, c_2, ... c_n\),再变一下形得到:

\[\prod_{j=1}^{m}w_{p_j}*\sum_{(\sum_{i=1}^{n}c_i) = n-2-m}(\prod_{i=1}^{n}\frac{w_{i}^{c_i}}{c_i!}) = \prod_{j=1}^{m}w_{p_j}*\frac{(\sum_{i=1}^{n}w_i)^{n-2-m}}{(n-2-m)!}
\]

终于化成了我们想要的东西。

再将上面那个套入我们的答案表达式中,即可得到:

\[ans = \sum_{m=0}^{n-2}(\sum_{1 \le p_1 < p_2 < ... < p_m \le n}\prod_{j=1}^{m}w_{p_j})*\frac{(\sum_{i=1}^{n}w_i)^{n-2-m}}{(n-2-m)!}
\]

中间那个看似很鬼畜的式子用 dp 处理一下就好啦。时间复杂度 O(n^2)。

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 2000;
const int MOD = int(1E9) + 7;
class ConnectedStates{
public:
int pow_mod(int b, int p) {
int ret = 1;
while( p ) {
if( p & 1 ) ret = 1LL*ret*b%MOD;
b = 1LL*b*b%MOD;
p >>= 1;
}
return ret;
}
int dp[MAXN + 5], w[MAXN + 5], pro, n;
int fct[MAXN + 5], ifct[MAXN + 5], pw[MAXN + 5];
void get_ready() {
dp[0] = 1;
for(int i=1;i<=n;i++)
for(int j=n;j>=1;j--)
dp[j] = (dp[j] + 1LL*dp[j-1]*w[i]%MOD)%MOD;
pw[0] = 1, pw[1] = 0, pro = 1;
for(int i=1;i<=n;i++)
pw[1] = (pw[1] + w[i])%MOD, pro = 1LL*pro*w[i]%MOD;
for(int i=2;i<=n;i++)
pw[i] = 1LL*pw[i-1]*pw[1]%MOD;
fct[0] = 1;
for(int i=1;i<=n;i++)
fct[i] = 1LL*fct[i-1]*i%MOD;
ifct[n] = pow_mod(fct[n], MOD - 2);
for(int i=n-1;i>=0;i--)
ifct[i] = 1LL*ifct[i+1]*(i+1)%MOD;
}
int getSum(vector<int>vec) {
n = vec.size();
for(int i=1;i<=n;i++)
w[i] = vec[i-1];
get_ready();
int ret = 0;
for(int i=0;i<=n-2;i++)
ret = (ret + 1LL*dp[i]*pw[n-2-i]%MOD*ifct[n-2-i]%MOD)%MOD;
return 1LL*ret*fct[n-2]%MOD*pro%MOD;
}
};

@details@

当我看到这个做法的瞬间:woc 这是什么神仙操作。

果真人类智慧啊。

但我觉得这个数据范围好像fft可以过?

@topcoder - SRM697D1L3@ ConnectedStates的更多相关文章

  1. TopCoder kawigiEdit插件配置

    kawigiEdit插件可以提高 TopCoder编译,提交效率,可以管理保存每次SRM的代码. kawigiEdit下载地址:http://code.google.com/p/kawigiedit/ ...

  2. 记第一次TopCoder, 练习SRM 583 div2 250

    今天第一次做topcoder,没有比赛,所以找的最新一期的SRM练习,做了第一道题. 题目大意是说 给一个数字字符串,任意交换两位,使数字变为最小,不能有前导0. 看到题目以后,先想到的找规律,发现要 ...

  3. TopCoder比赛总结表

    TopCoder                        250                              500                                 ...

  4. Topcoder几例C++字符串应用

    本文写于9月初,是利用Topcoder准备应聘时的机试环节临时补习的C++的一部分内容.签约之后,没有再进行练习,此文暂告一段落. 换句话说,就是本文太监了,一直做草稿看着别扭,删掉又觉得可惜,索性发 ...

  5. TopCoder

    在TopCoder下载好luncher,网址:https://www.topcoder.com/community/competitive%20programming/ 选择launch web ar ...

  6. TopCoder SRM 596 DIV 1 250

    body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } P ...

  7. 求拓扑排序的数量,例题 topcoder srm 654 div2 500

    周赛时遇到的一道比较有意思的题目: Problem Statement      There are N rooms in Maki's new house. The rooms are number ...

  8. TopCoder SRM 590

     第一次做TC,不太习惯,各种调试,只做了一题...... Problem Statement     Fox Ciel is going to play Gomoku with her friend ...

  9. Topcoder Arena插件配置和训练指南

    一. Arena插件配置 1. 下载Arena 指针:http://community.topcoder.com/tc?module=MyHome 左边Competitions->Algorit ...

随机推荐

  1. 蛋疼的JavaScript(二)this

    ### 烦人的this JavaScript的表现与之前学的任何传统的语言都不一样,这个就很烦人,这几天把这个坑扫除了 ### this到底指向什么 总的来说,总结下,this其实取决于调用者的上下文 ...

  2. Java问题解读系列之String相关---String类的常用方法?

    今天的题目是:String类的常用方法? 首先,我们在eclipse中定义一个字符串,然后使用alt+/就会出现String类的所有方法,如下图所示: 下面我就挑选一些常用的方法进行介绍: 首先定义两 ...

  3. CodeVS3958 火车进站

    3958 火车进站 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 大师 Master         题目描述 Description 火车站内往往设有一些主干线分叉出去的铁路支路 ...

  4. 你知道forEach和each的区别吗?

      要知道forEach和each的区别,你必须明白一点:forEach是js中的方法(针对数组),而each是jquery中的方法(针对jquery对象,即$( ) ).知道这一点,接下来我分别给举 ...

  5. spring源码学习之默认标签的解析(一)

    继续spring源码的学习之路,现在越来越觉得这个真的很枯燥的,而且我觉得要是自己来看源码,真的看不下去,不是没有耐心,而是真的没有头绪,我觉得结合着书来看,还是很有必要的,最起码大致的流程是能够捋清 ...

  6. day40-Spring 02-事务的回顾

  7. Sublime text 3 如何格式化HTML/css/js代码

    Sublime Text 3 安装Package Control   原来Subl3安装Package Control很麻烦,现在简单的方法来了 一.简单的安装方法 使用Ctrl+`快捷键或者通过Vi ...

  8. 2017校赛 问题 F: 懒人得多动脑

    题目描述 小D的家A和学校B都恰好在以点F为焦点的双曲线上,而小D每日所需的生活水源在一条平行该双曲线准线的直线上,设它的值为v.大家都知道,每天都是要喝水的,但是小D有点懒,他希望自己能在去上学或者 ...

  9. 用预编译包安装zabbix-agent

    如果主机无法上网,安装rpm又缺少依赖时,可以通过预编译包进行安装zabbix-agent,下载地址 https://www.zabbix.com/download 下载后,执行如下命令: wget ...

  10. Gym - 101962B_Color Changing Sofa

    题意:将一个沙发放到一个分成好几个色块(一个字母代表一种颜色)的房间里,要求沙发染成跟所在色块一样的颜色,沙发分成(0,1)两种,0可以染成一种颜色,1可以染成一种颜色(换句话说,沙发最多两种颜色), ...