实际上这题的题面还是颇有意思,对两个划分不同的定义暗示了第二类斯特林数,模数是\(1000000007\)又表明这题不是NTT。

那么一开始的想法是考虑每个集合的贡献。设这个集合为\(S\),那么它的贡献为\(|S|\begin{Bmatrix}n-|S|\\k-1 \end{Bmatrix} \sum_{i \in S} w_i\),而所有大小为\(t\)的集合的元素和为\({{n-1}\choose{t-1}}\sum_{i=1}^n w_i\),故最终答案为\(\sum_{i=1}^n w_i \sum_{j=1}^n j {{n-1}\choose{j-1}} \begin{Bmatrix} n-j\\k-1 \end{Bmatrix}\)。

然后正如评论区里的那位叫\(\color{purple} { \text {Blue233333}}\)老兄所说,这个公式萎了。我们需要考虑新的计数方式。

考虑每个元素的贡献。那么答案就是\(\sum_{i=1}^n w_i \sum_{j=1}^{n} j \times f(n,k,j)\),其中\(f(n,k,j)\)表示把\(n\)个不同元素分到\(k\)个无序的集合中,且标号为1(或者什么别的)的元素所在的集合大小为\(j\)的方案数。

我们记\(g(n,k,i,j)\)表示把\(n\)个不同元素分到\(k\)个无序的集合中,且标号为\(i\)的元素与标号为\(j\)的元素在同一个集合中的方案数。同样地,记\(h(n,k,i,j,s)\)表示把\(n\)个不同元素分到\(k\)个无序的集合中,且标号为\(i\)的元素与标号为\(j\)的元素在同一个大小为\(s\)的集合中的方案数。显然,有\(\sum_{s=1}^n h(n,k,i,j,s) = g(n,k,i,j)\)。

那么,我们有\(j \times f(n,k,j) = \sum_{i=1}^n h(n,k,1,i,j)\),消去了\(j\),这是因为每一种分配方式都被恰好重复计数\(j\)次。故答案等于\(\sum_{j=1}^n g(n,k,1,j)\)。

显然,有

\[g(n,k,i,j) =
\begin{cases}
\begin{Bmatrix} n \\ k \end{Bmatrix}, & \text {if $ i = j $} \\
\begin{Bmatrix} n-1 \\ k \end{Bmatrix}, & \text {if $i \neq j$}
\end{cases}\]

那么,答案就是\((\begin{Bmatrix} n \\ k \end{Bmatrix} + (n-1)\begin{Bmatrix} n-1 \\ k \end{Bmatrix}) \sum _ {i=1} ^ n w_i\)。

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

当然,这也就说明了\(\sum_{j=1}^n j {{n-1}\choose{j-1}} \begin{Bmatrix} n-j\\k-1 \end{Bmatrix} = \begin{Bmatrix} n \\ k \end{Bmatrix} + (n-1)\begin{Bmatrix} n-1 \\ k \end{Bmatrix}\)。希望有大佬给出这个的代数证明。

#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7, N = 200010;
typedef long long ll;
ll power(ll a,int b) {
ll res = 1ll;
while (b) {
if (b&1) (res *= a) %= MOD;
(a *= a) %= MOD;
b >>= 1;
}
return res;
}
ll jc[N],inv[N],sum,ans;
ll comb(int a,int b) {
return (a < 0 || b < 0 || a < b) ? 0 : \
jc[a] * inv[a-b] % MOD * inv[b] % MOD;
}
int n,k,w;
int main() {
scanf("%d%d",&n,&k);
for (int i = 1 ; i <= n ; ++ i)
scanf("%d",&w), (sum += w) %= MOD;
jc[0] = 1ll;
for (int i = 1 ; i <= n ; ++ i)
jc[i] = jc[i-1] * i % MOD;
inv[n] = power(jc[n],MOD - 2);
for (int i = n-1 ; i >= 0 ; -- i)
inv[i] = inv[i+1] * (i+1) % MOD;
for (int i = 1, j = (k&1) ? 1 : -1 ; i <= k ; ++ i, j = -j) {
ans += j * comb(k,i) * power(i,n-1) % MOD;
ans = (ans % MOD + MOD) % MOD;
}
(ans *= n-1) %= MOD;
for (int i = 1, j = (k&1) ? 1 : -1 ; i <= k ; ++ i, j = -j) {
ans += j * comb(k,i) * power(i,n) % MOD;
ans = (ans % MOD + MOD) % MOD;
}
(ans *= sum) %= MOD;
(ans *= inv[k]) %= MOD;
cout << ans << endl;
return 0;
}

小结:在组合计数问题上另辟蹊径,除解题之外还能带来奇妙的结论。

【做题】CFedu41G. Partitions——推式子的更多相关文章

  1. P3768 简单的数学题 杜教筛+推式子

    \(\color{#0066ff}{ 题目描述 }\) 由于出题人懒得写背景了,题目还是简单一点好. 输入一个整数n和一个整数p,你需要求出(\(\sum_{i=1}^n\sum_{j=1}^n ij ...

  2. AtCoder Grand Contest 1~10 做题小记

    原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-1-to-10.html 考虑到博客内容较多,编辑不方便的情 ...

  3. BZOJ做题记录[0512~?]

    觉得做一道开一篇真不好...好多想找的东西都被刷下去了... 至于?的日期究竟到什么时候...还是看心情...但是估计不会超过七天吧 最后更新时间:05/19 10:42 [05/14 10:56]我 ...

  4. 退役IV次后做题记录

    退役IV次后做题记录 我啥都不会了.... AGC023 D 如果所有的楼房都在\(S\)同一边可以直接得出答案. 否则考虑最左最右两边的票数,如果左边>=右边,那么最右边会投给左边,因为就算车 ...

  5. HNOI做题记录

    算是--咕完了? 2013.2014的就咕了吧,年代太久远了,并且要做的题还有那么多-- LOJ #2112. 「HNOI2015」亚瑟王 发现打出的概率只和被经过几次有关. 于是\(dp_{i,j} ...

  6. SHOI做题记录

    LOJ #2027. 「SHOI2016」黑暗前的幻想乡 考虑到每个公司一条边,那就等价于没有任何一家公司没有边. 然后就可以容斥+矩阵树定理,没了. LOJ #2028. 「SHOI2016」随机序 ...

  7. NOIP2016考前做题(口胡)记录

    NOIP以前可能会持续更新 写在前面 NOIP好像马上就要到了,感觉在校内训练里面经常被虐有一种要滚粗的感觉(雾.不管是普及组还是提高组,我都参加了好几年了,结果一个省一都没有,今年如果还没有的话感觉 ...

  8. Codeforces 1528F - AmShZ Farm(转化+NTT+推式子+第二类斯特林数)

    Codeforces 题目传送门 & 洛谷题目传送门 神仙题,只不过感觉有点强行二合一(?). 首先考虑什么样的数组 \(a\) 符合条件,我们考虑一个贪心的思想,我们从前到后遍历,对于每一个 ...

  9. ACM 做题过程中的一些小技巧。

    ACM做题过程中的一些小技巧. 1.一般用C语言节约空间,要用C++库函数或STL时才用C++; cout.cin和printf.scanf最好不要混用. 2.有时候int型不够用,可以用long l ...

随机推荐

  1. QT5 QT4--LNK2019 无法解析的外部符号

    新创建的工程 #include <QtWidgets/QApplication> #include <QtWidgets/QWidget> #include <QtWid ...

  2. 08 集合[11,22,33,44,55,66,77,88,99],将所有<66的值保存至字典的第一个key中,将所有>=66的值保存至字典的第二个key中。即:{'k1':<66的所有值,'k2':>=66的所有值}

    li = [11,22,33,44,55,66,77,88,99]dict = {'k1':[],'k2':[]}for i in li:    if i < 66:        dict[& ...

  3. Spark学习之路 (十)SparkCore的调优之Shuffle调优

    摘抄自https://tech.meituan.com/spark-tuning-pro.html 一.概述 大多数Spark作业的性能主要就是消耗在了shuffle环节,因为该环节包含了大量的磁盘I ...

  4. Linux QtCreator 编译报错:No rule to make target '.../***' needed by '***.o'.stop

    Linux QtCreator 编译报错:No rule to make target 'mainwindow.cpp'  needed by  'mainwindow.o'.stop [1]解决方案 ...

  5. python之小数据池

    代码块 Python 程序 是由代码块构造的.块是一个python程序的文本,它是作为一个执行单元的. 代码块:一个模块,一个函数,一个类,一个文件等都是一个代码块. 而作为交互方式输入的每个命令都是 ...

  6. 这份书单,给那些想学Hadoop大数据、人工智能的人

    一.简单科普类 (文末附下载链接) 1.<人工智能:李开复谈AI如何重塑个人.商业与社会的未来图谱2> 作者:李开复,王咏刚 推荐理由:文章写得一般,但李开复和王永刚老师总结的还可以,算国 ...

  7. linux下安装mysql(rpm文件安装)

    数据库包下载: https://www.mysql.com/downloads/ 在GPL开原协议的社区开源版里边下载 我们用mysql community server里边的 其中workbench ...

  8. 转:[你必须知道的异步编程]——异步编程模型(APM)

    本专题概要: 引言 你知道APM吗? 你想知道如何使用异步编程模型编写代码吗? 使用委托也可以实现异步编程,你知道否? 小结 一.引言 在前面的C#基础知识系列中介绍了从C#1.0——C#4.0中一些 ...

  9. JS中的函数节流throttle详解和优化

    JS中的函数节流throttle详解和优化在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(mousemove),这种事件有一个特点,在一个正常的操作中,有可能在一个短的 ...

  10. linux 禁止22端口号

    重启防火墙命令#systemctl restart iptables.service 查看端口号#iptables -L首先修改配置文件 vi /etc/ssh/sshd_config 增加新端口号P ...