[CF932E]Team Work & [BZOJ5093]图的价值

CF题面
题意:求\(\sum_{i=0}^{n}\binom{n}{i}i^k\)
\(n\le10^9,k\le5000\)
模\(10^9+7\)
BZOJ题面
题意:求\(n*2^{\frac{n(n-1))}{2}-(n-1)}*\sum_{i=0}^{n-1}\binom{n-1}{i}i^k\)
\(n\le10^9,k\le2*10^5\)
模\(998244353\)

第二类斯特林数

赶紧去学第二类斯特林数啊
第二类斯特林数:\(S(n,m)\),表示把\(n\)个不同的的球放到\(m\)个相同的盒子且不允许空盒的方案数。
首先有一个\(O(n^2)\)的递推。考虑第\(n\)个球的放置,如果单独放置方案数就等于\(S(n-1,m-1)\),否则就是\(m*S(n-1,m)\),表示枚举放在那个盒子里。写出来就是
\[S(n,m)=S(n-1,m-1)+m*S(n-1,m)\]
边界条件:\(S(0,0)=1,S(i,0)=0(i>0)\)
然后还有各种考虑组和意义得出来的柿子
第二类斯特林数存在通项公式。因为\(m^n\)表示把\(n\)个不同的球放到\(m\)个不同的盒子里且允许空盒的方案数,我们想办法用这个东西构造出第二类斯特林数的组和意义。
首先盒子是否相同很好办,直接乘/除以\(m!\)即可。关键问题在于空盒的处理。
考虑容斥,计算“至少有\(k\)个空盒然后剩下的随便是不是空盒的方案数”,乘上一个容斥系数
\[S(n,m)=\frac{1}{m!}\sum_{k=0}^{m}(-1)^k\binom{m}{k}(m-k)^n\]
还有一个,反过来用第二类斯特林数来表示\(m^n\)
其实就是一个反演,但如果也同样考虑组和意义的话岂不妙哉。
枚举有几个盒子不是空的,可以直接得到如下柿子:
\[m^n=\sum_{i=0}^{m}S(n,i)*\binom{m}{i}*i!\]

sol

所以说这道题怎么做呢?
开始推柿子辣~
\[\sum_{i=0}^{n}\binom{n}{i}i^k=\sum_{i=0}^{n}\binom{n}{i}\sum_{j=0}^{i}S(k,j)*\binom{i}{j}*j!\\=\sum_{j=0}^{n}S(k,j)*j!\sum_{i=j}^{n}\binom{n}{i}\binom{i}{j}\\=\sum_{j=0}^{n}S
(k,j)*j!*\binom{n}{j}*2^{n-j}\\=\sum_{j=0}^{k}S
(k,j)*j!*\binom{n}{j}*2^{n-j}\]
柿子里面的阶乘\(j!\)、组合数\(\binom{n}{j}\)、2的次幂\(2^{n-j}\)都可以\(O(k)\)处理出来。复杂度瓶颈在于第二类斯特林数的处理。
\(k\le5000\)可以直接用递推式\(O(k^2)\)处理出来,而观察其通项式会发现其实就是一个卷积形式:
\[S(n,m)=\frac{1}{m!}\sum_{k=0}^{m}(-1)^k\binom{m}{k}(m-k)^n\\=\sum_{k=0}^{m}\frac{(-1)^k}{k!}*\frac{(m-k)^n}{(m-k)!}\]
所以直接上\(NTT\),复杂度\(O(k\log{k})\)
但是\(CF\)上的那道题不能用\(NTT\)诶,毕竟\(10^9+7\)怎么\(NTT\)

code

[CF932E]Team Work
这里我强行用通项公式然后写了个\(O(k^2)\)的多项式乘法

#include<cstdio>
#include<algorithm>
using namespace std;
const int mod = 1e9+7;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
int fastpow(int a,int b)
{
    int res=1;
    while (b) {if (b&1) res=1ll*res*a%mod;a=1ll*a*a%mod;b>>=1;}
    return res;
}
const int N = 5005;
int jc[N],C[N],two[N],inv,a[N],b[N],s[N],ans;
int main()
{
    int n=gi(),k=gi();
    jc[0]=1;
    for (int i=1;i<=k;++i) jc[i]=1ll*jc[i-1]*i%mod;
    C[0]=1;
    for (int i=1;i<=k;++i) C[i]=1ll*C[i-1]*(n-i+1)%mod*fastpow(i,mod-2)%mod;
    two[0]=fastpow(2,n);inv=fastpow(2,mod-2);
    for (int i=1;i<=k;++i) two[i]=1ll*two[i-1]*inv%mod;
    for (int i=0;i<=k;++i) a[i]=i&1?mod-fastpow(jc[i],mod-2):fastpow(jc[i],mod-2);
    for (int i=0;i<=k;++i) b[i]=1ll*fastpow(i,k)*fastpow(jc[i],mod-2)%mod;
    for (int i=0;i<=k;++i)
        for (int j=0;j<=i;++j)
            (s[i]+=1ll*a[j]*b[i-j]%mod)%=mod;
    for (int i=1;i<=k;++i) (ans+=1ll*s[i]*jc[i]%mod*C[i]%mod*two[i]%mod)%=mod;
    printf("%d\n",ans);
    return 0;
}

[BZOJ5093]图的价值

#include<cstdio>
#include<algorithm>
using namespace std;
const int _ = 800005;
const int mod = 998244353;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
int fastpow(int a,int b)
{
    int res=1;
    while (b) {if (b&1) res=1ll*res*a%mod;a=1ll*a*a%mod;b>>=1;}
    return res;
}
int n,N,k,l;
int jc[_],C[_],two[_],inv,a[_],b[_],rev[_],ans;
void NTT(int *P,int opt)
{
    for (int i=0;i<N;++i) if (i>rev[i]) swap(P[i],P[rev[i]]);
    for (int i=1;i<N;i<<=1)
    {
        int W=fastpow(3,(mod-1)/(i<<1));
        if (opt==-1) W=fastpow(W,mod-2);
        for (int j=0,p=i<<1;j<N;j+=p)
        {
            int w=1;
            for (int k=0;k<i;++k,w=1ll*w*W%mod)
            {
                int x=P[j+k],y=1ll*P[j+k+i]*w%mod;
                P[j+k]=(x+y)%mod;P[j+k+i]=(x-y+mod)%mod;
            }
        }
    }
    if (opt==-1)
    {
        int Inv=fastpow(N,mod-2);
        for (int i=0;i<N;++i) P[i]=1ll*P[i]*Inv%mod;
    }
}
int main()
{
    n=gi()-1;k=gi();
    jc[0]=1;
    for (int i=1;i<=k;++i) jc[i]=1ll*jc[i-1]*i%mod;
    C[0]=1;
    for (int i=1;i<=k;++i) C[i]=1ll*C[i-1]*(n-i+1)%mod*fastpow(i,mod-2)%mod;
    two[0]=fastpow(2,n);inv=fastpow(2,mod-2);
    for (int i=1;i<=k;++i) two[i]=1ll*two[i-1]*inv%mod;
    for (int i=0;i<=k;++i) a[i]=i&1?mod-fastpow(jc[i],mod-2):fastpow(jc[i],mod-2);
    for (int i=0;i<=k;++i) b[i]=1ll*fastpow(i,k)*fastpow(jc[i],mod-2)%mod;
    for (N=1;N<=k*2;N<<=1) ++l;--l;
    for (int i=0;i<N;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<l);
    NTT(a,1);NTT(b,1);
    for (int i=0;i<N;++i) a[i]=1ll*a[i]*b[i]%mod;
    NTT(a,-1);
    for (int i=0;i<=k;++i) (ans+=1ll*a[i]*jc[i]%mod*C[i]%mod*two[i]%mod)%=mod;
    int Pow=(1ll*n*(n+1)/2-n)%(mod-1);
    printf("%d\n",1ll*ans*fastpow(2,Pow)%mod*(n+1)%mod);
    return 0;
}

原文地址:https://www.cnblogs.com/zhoushuyu/p/8450141.html

时间: 2024-09-30 02:40:06

[CF932E]Team Work & [BZOJ5093]图的价值的相关文章

Bzoj5093: 图的价值

题面 Bzoj Sol 一张无向无重边自环的图的边数最多为\(\frac{n(n-1)}{2}\) 考虑每个点的贡献 \[n*2^{\frac{n(n-1)}{2} - (n-1)}\sum_{i=0}^{n-1}i^kC(n-1, i)\] 很好理解 考虑后面的\(\sum_{i=0}^{n-1}i^kC(n-1, i)\) \(i^k\)这里把它用第二类斯特林数表示出来 那么就是 \[\sum_{i=0}^{n-1}\sum_{j=0}^{i}S(k, j) j!C(i, j)\] \[=\

bzoj5093:图的价值(第二类斯特林数+NTT)

传送门 首先,题目所求为\[n\times 2^{C_{n-1}^2}\sum_{i=0}^{n-1}C_{n-1}^ii^k\] 即对于每个点\(i\),枚举它的度数,然后计算方案.因为有\(n\)个点,且关于某个点连边的时候剩下的边都可以随便连,所以有前面的两个常数 所以真正要计算的是\[\sum_{i=0}^{n-1}C_{n-1}^ii^k\] 根据第二类斯特林数的性质,有\[i^k=\sum_{j=0}^iS(k,j)\times j!\times C_i^j\] 然后带入,得\[\s

【BZOJ5093】图的价值(第二类斯特林数,组合数学,NTT)

[BZOJ5093]图的价值(第二类斯特林数,组合数学,NTT) 题面 BZOJ 题解 单独考虑每一个点的贡献: 因为不知道它连了几条边,所以枚举一下 \[\sum_{i=0}^{n-1}C_{n-1}^i·i^k·2^{\frac{n(n-1)}{2}}\] 因为有\(n\)个点,所以还要乘以一个\(n\) 所以,我们真正要求的就是: \[\sum_{i=0}^{n-1}C_{n-1}^i·i^k\] 怎么做? 看到了\(i^k\)想到了第二类斯特林数 \[m^n=\sum_{i=0}^{m}

【bzoj5093】[Lydsy1711月赛]图的价值(NTT+第二类斯特林数)

题意: 给定\(n\)个点,一个图的价值定义为所有点的度数的\(k\)次方之和. 现在计算所有\(n\)个点的简单无向图的价值之和. 思路: 将式子列出来: \[ \sum_{i=1}^n\sum_{j=0}^{n-1}{n-1\choose j}2^{\frac{(n-1)(n-2)}{2}}j^k \] 表示分别考虑每个点的贡献,我们只需要枚举其度数即可,其余的边任意连. 然后我们将后面的\(j^k\)用第二类斯特林数展开: \[ \begin{aligned} &\sum_{i=1}^{n

bzoj 5093 [Lydsy1711月赛]图的价值 NTT+第二类斯特林数

[Lydsy1711月赛]图的价值 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 245  Solved: 128[Submit][Status][Discuss] Description “简单无向图”是指无重边.无自环的无向图(不一定连通). 一个带标号的图的价值定义为每个点度数的k次方的和. 给定n和k,请计算所有n个点的带标号的简单无向图的价值之和. 因为答案很大,请对998244353取模输出. Input 第一行包含两个正整数n,k(

CF932E Team Work(第二类斯特林数)

求$\sum_{i=1}^nC_{n}^i*i^k$ 题解 1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 using namespace std; 5 const int N=5005,P=1e9+7,inv2=500000004; 6 inline int ksm(int a,int b){ 7 int res=1; 8 while(b){ 9 if(b&1) res=1ll*res*a%P; 10 a=1l

bzoj 5093 图的价值 —— 第二类斯特林数+NTT

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5093 每个点都是等价的,从点的贡献来看,得到式子: \( ans = n * \sum\limits_{d=0}^{n-1} d^{k} * 2^{C_{n-1}^{2}} * C_{n-1}^{d} \) 使用 \( n^{k} = \sum\limits_{i=0}^{k} S(k,i) * i! *C_{n}^{i} \) 得到 \( ans = n * \sum\limits_{d

CF932E Team Work

题面 题解 有一个非常玄学的公式: $ m^n=\sum_{i=0}^nC_m^i\times S(n,i)\times i! $ 看一下$\text{yyb}$的解释: $m^n$理解为把$n$个不同的球放到$m$个不同的盒子中去. 那么我们枚举有几个盒子非空,用第二类斯特林数乘阶乘计算放置的方案数,最后求和就是结果. 所以原式等于: $$ \sum_{i=1}^nC_n^i\sum_{j=0}^iC_i^j\times S(k,j)\times j! \\ =\sum_{i=1}^n\fra

CF932E Team Work——第二类斯特林数

题解 n太大,而k比较小,可以O(k^2)做 想方设法争取把有关n的循环变成O(1)的式子 考虑用公式: 来替换i^k 原始的组合数C(n,i)一项,考虑能否和后面的系数分离开来,直接变成2^n处理. 之后大力推式子 考虑要消掉n,就想办法把n往里面放,与和n有关的项外层枚举的话,相对就不动了.可以乘法分配律把n搞定. #include<bits/stdc++.h> #define reg register int #define il inline #define numb (ch^'0')