Noi2016十连测第二场-黑暗 (二项式定理/斯特林数+CDQ+NTT)

Noi2016十连测第二场-黑暗 (二项式定理/斯特林数+CDQ+NTT)

题意: n 个点的无向图,每条边都可能存在,一个图的权值是连通块个数的 m 次方,求所有可能的图的权值和。

考虑\(dp[i][j]\)表示\(j\)个点,权值为\(i\)次方

我们首先要预处理出\(n\)个点无向联通图的数量\(g[i]\),模板题:BZOJ-3456 题解

对于\(dp[i][j]\),枚举\(1\)号点所在的连通块大小为\(x\),那么可以得到的是\(dp[i][j]=\sum dp[k][j-x]\cdot C(j-1,x-1)\cdot C(i,k)\cdot g[x]\)(每次转移一个连通块,用二项式定理展开来求次方)

利用\(CDQ+NTT\)可以完成转移,模板题:HDU-5730 题解

#include<bits/stdc++.h>
using namespace std;

//#define int long long

#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
#define Mod2(x) ((x<0)&&(x+=P))
#define Mod1(x) ((x>=P)&&(x-=P))

template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }

char IO;
int rd(){
    int s=0,f=0;
    while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    do s=(s<<1)+(s<<3)+(IO^'0');
    while(isdigit(IO=getchar()));
    return f?-s:s;
}

const int N=1<<15|5,P=998244353;

bool be;
int n=3e4,m=15;
int Inv[N],Fac[N];
ll qpow(ll x,ll k) {
    ll res=1;
    for(;k;k>>=1,x=x*x%P) if(k&1) res=res*x%P;
    return res;
}

int g[N],h[N],dp[16][N],w[N];
int A[16][N],B[N];
int rev[N];
void NTT(int n,int *a,int f) {
    rep(i,1,n-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
    for(reg int i=1;i<n;i<<=1) {
        int len=n/i/2;
        for(reg int l=0;l<n;l+=2*i) {
            for(reg int j=l;j<l+i;j++) {
                int t=1ll*a[j+i]*w[(j-l)*len]%P;
                a[j+i]=a[j]-t; Mod2(a[j+i]);
                a[j]=a[j]+t; Mod1(a[j]);
            }
        }
    }
    if(f==-1) {
        ll base=qpow(n,P-2);
        rep(i,0,n-1) a[i]=a[i]*base%P;
    }
}

//预处理n个点联通图的数量g
void Solve1(int l,int r) {
    if(l==r) return;
    int mid=(l+r)>>1;
    Solve1(l,mid);
    int R=1,cc=-1;
    while(R<=r-l+1) R<<=1,cc++;
    rep(i,1,R) rev[i]=(rev[i>>1]>>1)|((i&1)<<cc);
    w[0]=1,w[1]=qpow(3,(P-1)/R);
    rep(i,2,R-1) w[i]=1ll*w[i-1]*w[1]%P;
    rep(i,0,R) A[0][i]=B[i]=0;
    rep(i,l,mid) A[0][i-l]=1ll*g[i]*Inv[i-1]%P;
    rep(i,1,r-l) B[i]=1ll*Inv[i]*h[i]%P;
    NTT(R,B,1),NTT(R,A[0],1);
    rep(i,0,R-1) A[0][i]=1ll*A[0][i]*B[i]%P;
    w[0]=1,w[1]=qpow((P+1)/3,(P-1)/R);
    rep(i,2,R-1) w[i]=1ll*w[i-1]*w[1]%P;
    NTT(R,A[0],-1);
    rep(i,mid+1,r) g[i]=(g[i]-1ll*A[0][i-l]*Fac[i-1]%P+P)%P;
    Solve1(mid+1,r);
}

int C[20][20];
void Solve(int l,int r) {
    if(l==r) return;
    int mid=(l+r)>>1;
    Solve(l,mid);
    int R=1,cc=-1;
    while(R<=r-l+1) R<<=1,cc++;
    rep(i,1,R) rev[i]=(rev[i>>1]>>1)|((i&1)<<cc);
    w[0]=1,w[1]=qpow(3,(P-1)/R);
    rep(i,2,R-1) w[i]=1ll*w[i-1]*w[1]%P;
    rep(i,0,R) B[i]=0;
    rep(i,1,r-l) B[i]=1ll*Inv[i-1]*g[i]%P;
    NTT(R,B,1);
    rep(i,0,15) {
        rep(j,0,R) A[i][j]=0;
        rep(j,l,mid) A[i][j-l]=1ll*dp[i][j]*Inv[j]%P;
        NTT(R,A[i],1);
        rep(j,0,R-1) A[i][j]=1ll*A[i][j]*B[j]%P;
    }
    w[0]=1,w[1]=qpow((P+1)/3,(P-1)/R);
    rep(i,2,R-1) w[i]=1ll*w[i-1]*w[1]%P;
    rep(i,0,15) {
        NTT(R,A[i],-1);
        rep(j,mid+1,r) A[i][j-l]=1ll*A[i][j-l]*Fac[j-1]%P;
    }
    rep(i,mid+1,r) rep(j,0,15) rep(k,0,j) dp[j][i]=(dp[j][i]+1ll*C[j][k]*A[k][i-l])%P;
    Solve(mid+1,r);
}

bool ed;
int main(){
    freopen("dark.in","r",stdin),freopen("dark.out","w",stdout);
    Fac[0]=Fac[1]=Inv[0]=Inv[1]=1;
    rep(i,2,n) {
        Fac[i]=1ll*Fac[i-1]*i%P;
        Inv[i]=1ll*(P-P/i)*Inv[P%i]%P;
    }
    rep(i,2,n) Inv[i]=1ll*Inv[i]*Inv[i-1]%P;
    rep(i,0,0) dp[i][0]=1;
    rep(i,0,n) g[i]=h[i]=qpow(2,i*(i-1)/2);
    rep(i,0,m) {
        C[i][0]=1;
        rep(j,1,i)  C[i][j]=(C[i-1][j]+C[i-1][j-1])%P;
    }
    Solve1(1,n);
    Solve(0,n);
    rep(kase,1,rd()) {
        n=rd(),m=rd();
        printf("%d\n",dp[m][n]);
    }
}

原文地址:https://www.cnblogs.com/chasedeath/p/12106697.html

时间: 2024-12-14 23:12:37

Noi2016十连测第二场-黑暗 (二项式定理/斯特林数+CDQ+NTT)的相关文章

[Noi2016十连测第三场]线段树

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 #define maxn 100005 8 #define maxk 4000005 9 int n,m,q,tot,t1,t2,ans,L[maxn][18],R[maxn][18]; 1

BZOJ NOI十连测 第二测 T2

思路:20%可以搜索.. 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #include<time.h> 7 #define ll long long 8 const ll Mod=998244353; 9 ll jc[300005],jcny[300005]; 10 int n

P4091 [HEOI2016/TJOI2016]求和(第二类斯特林数,ntt)

题面:https://www.luogu.org/problem/P4091 题解:\[\begin{array}{l}f(n) = \sum\limits_{i = 0}^n {\sum\limits_{j = 0}^i {{\rm{S}}(i,j) \cdot {2^{\rm{j}}} \cdot j!} } \\ = \sum\limits_{i = 0}^n {\sum\limits_{j = 0}^n {{\rm{S}}(i,j) \cdot {2^{\rm{j}}} \cdot j!

【补题】多校联合训练第二场

第二场 1001 Is Derek lying? Problem Description Derek and Alfia are good friends.Derek is Chinese,and Alfia is Austrian.This summer holiday,they both participate in the summer camp of Borussia Dortmund.During the summer camp,there will be fan tests at i

百度之星2014初赛第二场

A. Scenic Popularity http://acm.hdu.edu.cn/showproblem.php?pid=4831 思路:景点区会控制休息区的Hot值,我们建立休息区到它最近的景点区的关系,注意处理冲突. 查询和修改都暴力进行,预处理关系,从左到右,然后从右到左遍历一遍即可,更新时候,从被修改的p位置,向两边,与p有关的休息区进行更新.总的时间复杂度O(T*n*K),10^8左右,不到1s可以解决. const int maxn = 10000; const int maxh

计蒜之道2015程序设计大赛初赛第二场——人人都有极客精神

计蒜之道2015程序设计大赛初赛第二场——人人都有极客精神 (一)体面 人人公司是一家极为鼓励极客精神的公司,当有重要的项目需要上线但又时间太紧,甚至需要当天上线的时候,往往会挂起海盗旗开启电子日期显示,让大家可以在对时间有更明确的感知的情况下,同心协力搞定重要的项目.海盗旗下方的电子屏显示的日期形式为 YYYYMMDD (年份占 4 位.月份占 2 位.天数占 2 位). 日期电子屏幕上每个数字对应的显示如下图: 从上图可以得知每个数字对应的笔画数,比如 2 的笔画数是 5,8 的笔画数是 7

将Linux和开源解决方案带到Azure云中第二场培训

因福州微软孵化器需要,3月27日下午给入孵企业进行第二场将Linux和开源解决方案带到Azure云中的培训. 本次培训的内容有: 概述:将开源技术带入 Azure 云中 Linux and OSS on Azure 如何将定制的 Linux & FreeBSD 环境迁入到 Azure Azure 上 Linux 虚拟机创建并通过 DSC For Linux 扩展来管理 在 Azure 中创建和管理 Docker 多容器环境

HDU 5742 It&#39;s All In The Mind (贪心) 2016杭电多校联合第二场

题目:传送门. 题意:求题目中的公式的最大值,且满足题目中的三个条件. 题解:前两个数越大越好. #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int gcd(int a,int b) { if(!b) return a; return gcd(b,a%b); } int main() { int t; ci

2014百度之星初赛(第二场)——Best Financing

2014百度之星初赛(第二场)--Best Financing Problem Description 小A想通过合理投资银行理财产品达到收益最大化.已知小A在未来一段时间中的收入情况,描述为两个长度为n的整数数组dates和earnings,表示在第dates[i]天小A收入earnings[i]元(0<=i<n).银行推出的理财产品均为周期和收益确定的,可描述为长度为m的三个整数数组start.finish和interest_rates, 若购买理财产品i(0<=i<m),需要