ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】BZOJ5093图的价值(二项式+NTT)

2019-07-15 17:50:25  阅读:241  来源: 互联网

标签:const int 题解 sum brace NTT pmatrix choose BZOJ5093


【题解】BZOJ5093图的价值(二项式+NTT)

今天才做这道题,是我太弱了

强烈吐槽c++这种垃圾语言tmd数组越界不re反倒去别的数组里搞事情我只想说QAQ

推了一张A4纸的式子

考虑每个点的度数,因为每个点虽然有标号但是是等价的,对于每个点,对于答案的贡献是\(x\),答案输出\(n\times x\)就好了,所以答案是
\[ n\sum_{i=1}^{n-1} i^{k} {n-1\choose i}2^{\frac {n(n-1)} 2-(n-1)} \]
顺次解释:度数\(^k\),选择\(i\)个别的点去连接,剩下的边随便连

无关项提出来
\[ n2^{\frac {n(n-1)} 2-(n-1)}\sum_{i=1}^{n-1} i^{k} {n-1\choose i} \]
现在就是要求
\[ \sum_{i=1}^{n-1} i^{k} {n-1\choose i} \]
自然幂数和公式
\[ i^k=\sum_{j=0}^{\min\{i,k\}} {k\brace j}\begin{pmatrix} i \\j\end{pmatrix}j! \]
套进去
\[ \sum_{i=1}^{n-1} \sum_{j=0}^{\min\{i,k\}} {k\brace j}\begin{pmatrix} i \\j\end{pmatrix}j! {n-1\choose i} \]
先枚举\(j\)
\[ \sum_{j=0}^{n-1}\sum_{i=j}^{n-1}{k\brace j}j!{n-1\choose i}{i\choose j} \]
整理
\[ \sum_{j=0}^{n-1}{k\brace j}j!\sum_{i=j}^{n-1}{n-1\choose i}{i\choose j} \]
套一下公式(备胎模型)
\[ \sum_{j=0}^{n-1}{k\brace j}j!\sum_{i=j}^{n-1}{n-1-j\choose j}{n-1-j\choose i-j} \]
又可以提出来
\[ \sum_{j=0}^{n-1}{k\brace j}{n-1-j\choose j}j!\sum_{i=j}^{n-1}{n-1-j\choose i-j} \]
稍微改变一下形式
\[ \sum_{j=0}^{n-1}{k\brace j}{n-1-j\choose j}j!\sum_{c=i-j=0}^{c=i-j\le n-1-j}{n-1-j\choose c} \]
二项式定理套
\[ \sum_{j=0}^{n-1}{k\brace j}{n-1-j\choose j}j!2^{n-1-j} \]
我们晓得当\(k > j\)时式子的值\(=0\),所以枚举到\(\min \{n-1,k\}\)就好了。问题在于如何快速求那个斯特林数

斯特林数的容斥式
\[ {k\brace j}=\dfrac 1{j!} \sum_{i=0}^{j-1} (-1)^i{\begin{pmatrix}j\\i\end{pmatrix}}(j-i)^{k} \]
拆拆又是一个NTT的式子,不赘述了,看上面那个链接博客里有

答案式子
\[ n2^{\frac {n(n-1)} 2-(n-1)}\sum_{j=0}^{n-1}{k\brace j}{n-1-j\choose j}j!2^{n-1-j} \]
指数上取膜,又是欧拉定理

写一下NTT就好了

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>


using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}

namespace poly{
      const int maxn=1<<19|1;
      int a[maxn],b[maxn],r[maxn];
      int savlen;
      inline void getr(const int&len){
        if(len==savlen)return;
        int cnt=0;
        for(register int t=1;t<len;t<<=1)++cnt;
        for(register int t=1;t<len;++t)
          r[t]=r[t>>1]>>1|(t&1)<<cnt>>1;
      }
      const int mod=998244353;
      const int g=3;
      inline int ksm(int base,int p){
        register int ret=1;
        for(base%=mod;p;p>>=1,base=1ll*base*base%mod)
          if(p&1) ret=1ll*ret*base%mod;
        return ret;
      }
      const int gi=ksm(3,mod-2);
      inline void NTT(int*a,const int&len,const int&tag){
        getr(len);
        for(register int t=1;t<len;++t)
          if(r[t]>t) swap(a[t],a[r[t]]);
        int *a1,*a0,s=g;
        if(tag!=1) s=gi;
        for(register int t=1,wn;t<len;t<<=1){
          wn=ksm(s,(mod-1)/(t<<1));
          for(register int i=0;i<len;i+=t<<1){
            a1=(a0=a+i)+t;
            for(register int j=0,w=1,tm;j<t;++j,++a1,++a0,w=1ll*w*wn%mod){
                  tm=1ll**a1*w%mod;
                  *a1=(*a0-tm)%mod;
                  *a0=(*a0+tm)%mod;
                  if(*a1<0)*a1+=mod;
            }
          }
        }
        if(tag!=1)
          for(register int t=0,in=ksm(len,mod-2);t<len;++t)
            a[t]=1ll*a[t]*in%mod;
      }
}


using poly::mod;
using poly::NTT;
using poly::ksm;
const int maxn=2e5+5;
int jc[maxn],inv[maxn];
int t1[1<<19|1];
int s[1<<19|1];
int n,k,L,len;
int ret,ans;

inline void pre(){
      jc[0]=inv[0]=1;
      for(register int t=1;t<maxn;++t)
        jc[t]=1ll*jc[t-1]*t%mod;
      inv[maxn-1]=ksm(jc[maxn-1],mod-2);
      for(register int t=maxn-2;t;--t){
        inv[t]=1ll*inv[t+1]*(t+1)%mod;
        //if(t<15)cout<<"qaq="<<inv[t]<<endl;
        if(inv[t]==0) return void(cout<<"t="<<t<<endl);
      }
}

inline int c(const int&n,const int&m){
      if(n<m)return 0;
      return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}


int main(){
      pre();
      n=qr();k=qr();
      L=min(n-1,k);
      len=1;
      while(len<=L)len<<=1;
      for(register int t=0;t<=L;++t){
        s[t]=inv[t];
        if(t&1) s[t]=mod-s[t];
        t1[t]=1ll*inv[t]*ksm(t,k)%mod;
      }

      
      NTT(t1,len<<1,1);NTT(s,len<<1,1);
      
      for(register int t=0;t<len<<1;++t) s[t]=1ll*s[t]*t1[t]%mod;
      NTT(s,len<<1,-1);
      for(register int t=k+1;t<len<<1;++t) s[t]=0;
      int p=(1ll*n*(n-1ll)/2%(mod-1)-n+1+mod-1)%(mod-1);
      ret=1ll*ksm(2,p)*(n%mod)%mod;
      int w=1;
      for(register int t=0;t<=L;++t){
        ans=(ans+1ll*jc[t]*w%mod*ksm(2,n-1-t)%mod*s[t]%mod)%mod;
        w=1ll*w*(n-1-t)%mod*inv[t+1]%mod*jc[t]%mod;
      }
      cout<<1ll*ret*ans%mod<<endl;
      return 0;
}

标签:const,int,题解,sum,brace,NTT,pmatrix,choose,BZOJ5093
来源: https://www.cnblogs.com/winlere/p/11190351.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有