点此看题面

大致题意: 有一个长度为\(n\)的数列,每个位置上数字的值在\([1,m]\)范围内,则共有\(m^n\)种可能的数列。分别求出每个数列中本质不同的子序列个数,然后求和。

一些分析

首先,我们单独考虑空序列的个数\(m^n\),然后接下来就可以只考虑非空序列的个数了。

假设有一个长度为\(i\)的子序列(\(1\le i\le n\)),且其在序列中的位置分别为\(pos_1,pos_2,...,pos_i\),值分别为\(val_1,val_2,...,val_i\)。

则我们强制在\(1\sim pos_1-1\)范围内不能出现\(val_1\),\(pos_1+1\sim pos_2-1\)范围内不能出现\(val_2\),以此类推。

所以,在前\(pos_i\)个位置中,除\(pos_{1\sim i}\)这\(i\)个位置填\(val_{i\sim i}\)外,如上所述,其余\(pos_i-i\)个位置各有\(m-1\)种填法。

而在第\(pos_i\)个位置之后就可以随便填了,每个位置都有\(m\)种填法。

推式子

通过之前的分析,于是得到式子如下:

\[\sum_{i=1}^nm^i\sum_{j=i}^nC_{j-1}^{i-1}(m-1)^{j-i}m^{n-j}
\]

对于这个式子的解释:

首先,用\(i\)枚举子序列长度,而长度为\(i\)的子序列共有\(m^i\)种可能。

接下来\(j\)枚举\(pos_i\),而\(pos_{1\sim i-1}\)依次选择\([1,pos_i-1]\)(即这里的\([1,j-1]\))这个范围内的任意位置都是合法的,就相当于在\(j-1\)个位置中选择\(i-1\)个位置,方案数就是\(C_{j-1}^{i-1}\)。

从前文可得,\(pos_i-i\)(即这里的\(j-i\))个位置有\(m-1\)种填法,\(n-pos_i\)(即这里的\(n-j\))个位置有\(m\)种填法。

于是便得到上述式子。

然后就是化简:

先移项,把\(m^i\)移进去得到:

\[\sum_{i=1}^n\sum_{j=i}^nC_{j-1}^{i-1}(m-1)^{j-i}m^{n-j+i}
\]

改变枚举顺序,得到:

\[\sum_{j=1}^n\sum_{i=1}^jC_{j-1}^{i-1}(m-1)^{j-i}m^{n-j+i}
\]

观察到组合数中的\(i-1\)和\(j-1\),不难想到直接将枚举的\(i,j\)减\(1\),即:

\[\sum_{j=0}^{n-1}\sum_{i=0}^{j-1}C_j^i(m-1)^{(j+1)-(i+1)}m^{n-(j+1)+(i+1)}
\]

然后我们可以化简一下系数,发现这些\(1\)和\(-1\)恰好抵消了,得到:

\[\sum_{j=0}^{n-1}\sum_{i=0}^{j-1}C_j^i(m-1)^{j-i}m^{n-j+i}
\]

然后我们拎出\(m^{n-j}\),就可以得到:

\[\sum_{j=0}^{n-1}m^{n-j}\sum_{i=0}^{j-1}C_j^i(m-1)^{j-i}m^i
\]

那这样有什么好处呢?

回想一下二项式定理:\((x+y)^n=\sum_{i=0}^{n-1}x^iy^{n-i}\)。

这似乎与上面式子的后半部分有几分相似。

于是就可以化简得到:

\[\sum_{j=0}^{n-1}m^{n-j}((m-1)+m)^j=\sum_{j=0}^{n-1}m^{n-j}(2m-1)^j
\]

这个式子可以\(O(nlogn)\)快速幂计算,也可以直接\(O(n)\)计算。

总而言之,可以过了。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000000
#define X 1000000007
#define Qinv(x) Qpow(x,X-2)
#define Inc(x,y) ((x+=(y))>=X&&(x-=X))
using namespace std;
int n,m;
I int Qpow(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}//快速幂
int main()
{
RI i,ans,p1,p2,b1,b2;
scanf("%d%d",&n,&m),ans=p1=Qpow(m,n),p2=1,b1=Qinv(m),b2=(1LL*2*m-1)%X;//初始化
for(i=0;i^n;++i) Inc(ans,1LL*p1*p2%X),p1=1LL*p1*b1%X,p2=1LL*p2*b2%X;//O(n)计算答案
return printf("%d",ans),0;//输出答案
}

【CF660E】Different Subsets For All Tuples(组合数学)的更多相关文章

  1. 【组合数学】cf660E. Different Subsets For All Tuples

    比较套路的组合数学题 For a sequence a of n integers between 1 and m, inclusive, denote f(a) as the number of d ...

  2. cf660E Different Subsets For All Tuples

    For a sequence a of n integers between 1 and m, inclusive, denote f(a) as the number of distinct sub ...

  3. 【CF660E】Different Subsets For All Tuples 结论题

    [CF660E]Different Subsets For All Tuples 题意:对于所有长度为n,每个数为1,2...m的序列,求出每个序列的本质不同的子序列的数目之和.(多个原序列可以有相同 ...

  4. Educational Codeforces Round 11 E. Different Subsets For All Tuples 动态规划

    E. Different Subsets For All Tuples 题目连接: http://www.codeforces.com/contest/660/problem/E Descriptio ...

  5. Codeforces 660E Different Subsets For All Tuples【组合数学】

    看了官方题解+q神的讲解才懂... 智商问题.. 讲道理..数学真的比脱单难啊... 题目链接: http://codeforces.com/problemset/problem/660/E 题意: ...

  6. Different Subsets For All Tuples CodeForces - 660E (组合计数)

    大意: 定义$f(a)$表示序列$a$本质不同子序列个数. 给定$n,m$, 求所有长$n$元素范围$[1,m]$的序列的$f$值之和. 显然长度相同的子序列贡献是相同的. 不考虑空串, 假设长$x$ ...

  7. FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ

    因为垃圾电脑太卡了就重开了一个... 前传:多项式Ⅰ u1s1 我预感还会有Ⅲ 多项式基础操作: 例题: 26. CF438E The Child and Binary Tree 感觉这题作为第一题还 ...

  8. 2019.03.14 ZJOI2019模拟赛 解题报告

    得分: \(100+100+0=200\)(\(T1\)在最后\(2\)分钟写了出来,\(T2\)在最后\(10\)分钟写了出来,反而\(T3\)写了\(4\)个小时爆\(0\)) \(T1\):风王 ...

  9. Codeforces 895.C Square Subsets

    C. Square Subsets time limit per test 4 seconds memory limit per test 256 megabytes input standard i ...

随机推荐

  1. 字符串 Instant 互转

    Instant inst = Instant.now(); System.out.println(inst);//2018-05-15T02:27:09.909Z String s1 = s.subs ...

  2. PHP任意文件上传漏洞(CVE-2015-2348)

    安全研究人员今天发布了一个中危漏洞——PHP任意文件上传漏洞(CVE-2015-2348). 在上传文件的时候只判断文件名是合法的文件名就断定这个文件不是恶意文件,这确实会导致其他安全问题.并且在这种 ...

  3. Socket 代码收藏

    class SocketHelper    {        public delegate void Uplistbox(string txt);        public Uplistbox u ...

  4. leetcode 437. 路径总和 III

    题目描述: 给定一个二叉树,它的每个结点都存放着一个整数值. 找出路径和等于给定数值的路径总数. 路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点). 二 ...

  5. js字符串与数字之间的比较

    //1.纯数字之间比较 console.log(1<3);//true //2.纯字符串比较,先转成ASCII码,按位依次比较 console.log("1"<&quo ...

  6. .NET接收邮件下载邮件附件——openpop.net

    使用OpenPop.Net接收邮件很方便,下面是接收下载邮件附件的代码 OpenPop.Net下载地址 https://sourceforge.net/projects/hpop/ public cl ...

  7. 所有节点配置NTP服务

    主节点: 打开vim /etc/ntp.conf文件 For more information about this file, see the man pages # ntp.conf(), ntp ...

  8. 多线程编程_CyclicBarrier

    1.类说明: 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 Cycl ...

  9. python spilt()函数的使用方法

    Python中的split()函数的用法 Python中有split()和os.path.split()两个函数,具体作用如下:split():拆分字符串.通过指定分隔符对字符串进行切片,并返回分割后 ...

  10. Broken Keyboard (a.k.a. Beiju Text) UVA - 11988 (链表)

    题目链接:https://vjudge.net/problem/UVA-11988 题目大意:输入一个字符串,输出在原本应该是怎么样的?  具体方法是 碰到' [ ' 回到最前面  碰到‘ ]’  回 ...