@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. 常见的HTML标签的嵌套规则

    众所周知,HTML标签有两类: 块级元素div.h1~h6.address.blockquote.center.dir.dl.dt.dd.fieldset.form.hr.isindex.menu.n ...

  2. GIT → 04:Git与代码托管平台

    4.1 Git 与 GitHub比较 Git 是一个版本管理工具 , 只在本地使用的一个版本管理工具,其作用就是可以让你更好的管理你的程序,比如你原来提交过的内容,后面虽然修改过,但是通过git这个工 ...

  3. Vue.之.项目开发工具选用

    Vue.之.项目开发工具选用 上篇文章记录了创建项目,这篇文件记录,如何对创建的项目进行开发.这里选择一个工具:Visual Studio Code (请自行下载安装) 1. 打开VSCode工具,并 ...

  4. Linux 基础命令4进程

    ID和PID的产生 ps( process status) 查看现在的进程 上例中,列出了两个进程,进程 5198 和进程 10129,各自代表命令 bash 和 ps.正如我们所看到的, 默认情况下 ...

  5. golang学习资料必备

    核心资料库 https://github.com/yangwenmai/learning-golang

  6. ML面试1000题系列(31-40)

    本文总结ML面试常见的问题集 转载来源:https://blog.csdn.net/v_july_v/article/details/78121924 31.下列哪个不属于CRF模型对于HMM和MEM ...

  7. VS插件集合

    VS的强大不仅仅在于VS本身的强大. 同时,也有很多好用的插件,可以帮助我们更好的编辑代码, 提高效率. https://marketplace.visualstudio.com/search?tar ...

  8. Vue--过渡动画实现的三种方式

    一.使用vue的transition标签结合css样式完成动画 <!DOCTYPE html> <html lang="en"> <head> ...

  9. webpack学习之—— 模块热替换(Hot Module Replacement)

    模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换.添加或删除模块,而无需重新加载整个页面.主要是通过以下几种方式,来显著加快开发速度: 保留在完全重 ...

  10. Serializable 可串行化接口

    Serializable 可串行化接口 定义一个User类,实现Serializable接口: package com.monkey1025; import java.io.Serializable; ...