zoukankan      html  css  js  c++  java
  • [省选联考 2020 A 卷] 组合数问题

    前言:

    这是我退役赛省选中唯一一道答得令自己满意的题目。

    也就是

    $skyh:$难道你没$AC$

    的那道题。

    这道题我想了大概二十多分钟。觉得不是很简单。

    然而考后出来才发现,大神们都是用数学推导$AC$的这道题。

    而我,众所周知,退役在即的我菜的不行,自然不会数学推导。

    所以说如果你什么也不会,你怎么做这道题呢?

    于是这里有一个菜菜的组合含义理解方法。(几乎)没有任何数学推导。

    (可能和luogu的某些题解撞了?不知道我没看)

    虽然时间复杂度显然不优是$O(m^2log)$的但是应该比较好懂……(考场上犯傻了其实可以简单优化成$O(m^2)$)

    于是打算做一个大胆的尝试:能不能给学弟(妹)们讲懂。

    没关系看不懂就证明我果然还是太菜了QAQ

    $Description:$

    求$sumlimits_{k=0}^{n} inom{n}{k} x^k f(k)$其中$f(x)=sumlimits_{i=0}^{m} a_ix^i$

    15%:$nle 10^3$

    +25%:$m=0$

    +20%:$x=1$

    100%:$mle 10^3,others le 10^9$

    (只给出了我用到的部分分)

    $n le 10^3:$

    你可以用多项式多点求值求出所有$f$的值然后……编不下去了。

    (真庆幸没单独提出来一个$n le 5 imes 10^4$的部分分)

    $m=0:$

    也就是说$f(x)$是一个与$x$无关的常数。不妨设其为$1$最后乘上常数倍。

    式子的形式是:$sumlimits_{k=0}^{n} x^k inom{n}{k}$

    考虑实际含义:我们要对于所有$k$求出,从$n$个物品里选出$k$个,每种选法的贡献是$x^k$

    于是我们可以对于这$n$个物品考虑:每个物品被选中就贡献$x$,没被选中贡献$1$,一种选法的贡献就是所有物品乘起来。

    你要求出的是所有选法的贡献和,而物品之间是独立的,每种物品都会作为$1,x$出现各一次。

    所以其实就是$(1+x)^n$。把这个东西展开,就是乘法分配律,就得到的是所有方案的和。

    (然而写出啦我才知道,这不就是个二项式定理吗我考场上为啥要这么弱智啊)

    $x=1:$

    也就是说$x^k$那一项消失了。剩下的形式是$sumlimits_{k=0}^{n} f(k) inom{n}{k}$

    你自然拿多项式没什么办法,所以把它展开:

    $sumlimits_{i=0}^{m} a_i sumlimits_{k=0}^{n} k^i inom{n}{k}$

    外边的这个$i$大力枚举。考虑内部的组合含义:

    我要从$n$个物品里选出$k$个,然后贡献是$k^i$($i$是枚举的所以已知,可以视为常数)

    这个$k^i$好像有点难办,怎么去理解?就是从$k$个物品里可重复地选择$i$次啊。

    所以我们就是要从$n$个数里选$k$个,再在这$k$个里可重复钦定$i$次。

    卡住了。于是我们改变枚举的东西:我们尝试去枚举一下这$k$个物品里有多少个物品被至少钦定过一次,设为$j$。

    (因为你是可重复选择$i$次,所以枚举上届就是$i$,$i le m$复杂度没问题)

    那么我们从$n$个物品里选择$j$个作为被钦定过地元素:这是$inom{n}{j}$

    那么你要把$i$次选择分配给这$j$个元素,且每个元素非空。这显然是个第二类斯特林数。

    (啊学弟们是不是不知道什么是斯特林数啊,那我失败了啊,我好菜啊)

    然而其实只是一个$O(n^2)$递推的东西:$egin{Bmatrix} n \ k end{Bmatrix}$表示将$n$个带编号的球扔进$k$个不带标号桶里且每个桶都有球的方案数。

    然而在本道题当中,根据题目含义,桶是带标号的,所以还要乘上一个阶乘。这里的阶乘和上面的组合数形成下降幂$n^{underline{j}}$

    (这个东西学弟们可以当成一个dp来做)

    同时你还要考虑原来$n$个里选$k$个的过程:我们知道我们所钦定的$j$个元素一定被选了,没钦定的$n-j$个元素选不选都可以,总方案数是$2^{n-j}$

    所以总的方案数是$sumlimits_{i=0}^{m} a_i sumlimits_{j=0}^{i} n^{underline{j}} 2^{n-j} egin{Bmatrix} i \ j end{Bmatrix}$

    两层循环暴力枚举完事。组合数的话因为$n$是确定的所以直接搞一个下降幂就好了。

    无特殊限制:

    $sumlimits_{k=0}^{n} inom{n}{k} x^k f(k)$

    和上一个部分分一样先拆$f$得到$sumlimits_{i=0}^{m} a_i sumlimits_{k=0}^{n} k^i inom{n}{k} x^k $

    和上一个部分分一样我们改变含义去枚举$j$表示被钦定的元素个数,然后接着分析:

    其实除了$2^{n-j}$那部分以外,其余都和上面一样可以得到$n^{underline{j}} egin{Bmatrix} i \ j end{Bmatrix}$

    然后因为$x$不再是$1$所以我们不是要计数方案,而是统计方案的贡献和。其中的贡献和第一档部分分一样,选中是$x$没选中是$1$

    然后就比较简单了:你钦定的$j$个都一定被选中了是$x^j$,剩下的选不选都行,考虑所有情况就是$(x+1)^{n-j}$

    最后的答案是$sumlimits_{i=0}^{m} a_i sumlimits_{j=0}^{i} egin{Bmatrix} i \ j end{Bmatrix} x^j (x+1)^{n-j} n^{underline{j}}$

    我个弱智只预处理了斯特林数和下降幂,剩下的快速幂,$O(m^2log)$

    然而快速幂只用到了$x^{a},(x+1)^{n-a}$。$a le m$。所以说也可以简单预处理。复杂度下降到$O(m^2)$

    我相信学弟们一定没听懂。我太菜了

    我就是来骗阅读量的

    其实这道题这么顺下来部分分给的真棒啊……我喜欢。虽然并无卵用

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int $=1003;
     4 int st[$][$],mod,n,m,x,a[$],dpw[$],ans;
     5 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     6 int main(){
     7     scanf("%d%d%d%d",&n,&x,&mod,&m); st[0][0]=1;
     8     for(int i=1;i<=m;++i)for(int j=1;j<=i;++j)st[i][j]=(1ll*st[i-1][j]*j+st[i-1][j-1])%mod;
     9     for(int i=0;i<=m;++i)scanf("%d",&a[i]);
    10     for(int i=dpw[0]=1;i<=m;++i)dpw[i]=dpw[i-1]*(n-i+1ll)%mod;
    11     for(int i=0;i<=m;++i)for(int j=0;j<=i;++j)ans=(ans+1ll*a[i]*st[i][j]%mod*qp(x,j)%mod*qp(x+1,n-j)%mod*dpw[j])%mod;
    12     cout<<ans<<endl;
    13 }
    令人快活的13行AC代码
  • 相关阅读:
    shell基础之更改IP
    shell基础之if语句
    shell基础之变量及表达式
    shell基础之shell相关概念
    shell基础之bus实战(if 练习)
    shell基础之pxe批量部署
    shell基础之编译安装nginx
    Razor视图引擎基础语法
    EF三层
    EF简单增删改查
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/13325483.html
Copyright © 2011-2022 走看看