zoukankan      html  css  js  c++  java
  • 【2020杭电多校round5】HDU6818 Array Repairing

    题目大意

    题目链接

    对于一个给定的正整数(n),随机生成一个正整数序列(a[1dots n]),满足(forall iin[1,n]:a_iin[1,n])。注意,(a)不一定是排列。

    你需要通过若干次操作,使得(forall iin[1,n],a_i=i)。你可以进行的操作有两种:

    1. 选择一对位置(i,jin[1,n])(i eq j),交换(a_i,a_j)。一次操作花费为(1)
    2. 选择一个位置(iin[1,n])和一个数值(vin[1,n]),令(a_i:=v)。一次操作花费为(k)

    例如,如果你要进行(5)次1操作和(4)次2操作,则总花费为(4 imes k+5)

    ( ext{cost}_k(a))表示在参数(k)的条件下,将序列(a)变成(1,2,dots ,n)的最小花费。对(k=0,1,2),你需要分别求出( ext{cost}_k(a))的期望值(E( ext{cost}_k(a)))。输出(mod 998244353)意义下的值。

    给定(N)。对所有(nin[1,N])分别求答案。也就是说,你一共需要输出(3N)个数。

    数据范围:(1leq Nleq 5 imes10^5)

    本题题解

    我们称把(a)序列变成(1,2,dots,n)的过程为“还原”这个序列。一个位置(i)“已经还原”,就是指(a_i=i)

    首先,(k=0)时,代价一定为(0)

    subtask (k=1)

    考虑(k=1)的情况。我们从每个(i)(a_i)连一条有向边,则能得到一个基环(内向)树森林。发现,对每个环,设其长度为( ext{len}),我们使用( ext{len}-1)次1操作可以将其还原(环上每个点(a_i=i))。剩下的部分只能用2操作完成。容易证明这样花费是最小的。

    对于一个长度为(n)的序列(a),设它对应的基环树森林里,环的数量为(c)。则将(a)序列还原的最小花费就是(n-c)。注意,自环也算,也就是说“环的数量”和“连通块的数量”是等价的。

    要求期望,我们乘以序列的总数(n^n)以后,就转化为求所有序列的最小花费之和。又因为最小花费为(n- ext{环的数量})(sum(n- ext{环的数量})=sum n-sum ext{环的数量}=n^ncdot n-sum ext{环的数量})。问题转化为求(sum ext{环的数量}),也就是所有基环树森林,环的数量之和,记为(h(n))

    可以写出式子:(h(n)=sum_{i=1}^{n}(i-1)!{nchoose i}n^{n-i})。含义:((i-1)!)表示长度为(i)的环有多少种,({nchoose i})表示选出一些位置作为这个环,(n^{n-i})表示其他位置随意。不过要对每个(n)求一次,时间复杂度是(O(N^2))的,无法承受。比赛时,你可以暴力求出前几个(h)值,然后去oeis上找到这个序列:A190314。不过还有更好的方法。

    考虑用生成函数做。设(f(n))表示(n)个点的基环树数量(这里指的是一棵(n)个节点的、完整的基环树有多少种,而不是基环树森林)。这个(f)我们暂时还不会求。

    再设一个(g(n))表示(n)个点的基环树森林数量。这是很好求的,就等于(n^n)。设(F(x),G(x))分别是(f,g)指数型生成函数(即(F(x)=sum_{i=0}^{infty}f(x)frac{x^i}{i!})(G)同理)。则根据指数型生成函数的理论,可知:(G(x)=exp(F(x)))。所以(F(x)=ln(G(x)))。这样,通过做多项式(ln),我们就求出了(f)序列。

    知道了(f,g)以后。设(h)的指数型生成函数为(H(x)),则(H(x)=F(x)G(x))。这相等于,考虑每个基环树,对总数的贡献。单独拿出一棵(i)个节点的基环树,首先这样的基环树有(f(i))个,剩下的部分可以任意形成一个基环树森林,方案数就是(g(n-i))(注意,特别地,这里我们认为(g(0)=1)),而从(n)个点里选出这(i)个点的方案数是({nchoose i}),所以(h(n)=sum_{i=0}^{n}{nchoose i}f(i)g(n-i))。这正是指数型生成函数卷积的定义。

    总结来说,我们先搞一个序列(g(n)=n^n)。然后(G(x)cdot ln G(x)),就是我们要求的环的总数(h)了。答案就是(displaystylefrac{n^ncdot n-h(n)}{n^n})。(除以(n^n)是因为要求期望)。

    时间复杂度(O(Nlog N))

    subtask (k=2)

    (k=2)时,环上的点,我们还是用1操作来完成。考虑剩下的点。相当于要把每个点,变成它的儿子上面现在的值(显然每个儿子上的值是一样的)。所以对每个点,我们随便挑个儿子和它做交换(操作1)。直到叶子节点,没有儿子了,我们再用操作2。总的代价是(n- ext{环的数量}+ ext{叶子数量})

    环的数量我们已经会求了。考虑叶子数量。

    考虑每个点作为叶子时,对总数的贡献。它的贡献数,就等于钦定它是叶子后,其他点组成基环树森林的总方案数。也就是((n-1)^{n-1}),此外,这个点自己还要随便选一个父亲,所以要乘以(n-1),也就是((n-1)^{n})。这个思想挺妙的,把求所有基环树的叶子树之和,转化为了求每个叶子出现在多少基环树里。

    所以所有叶子的总贡献就是(ncdot (n-1)^n)。答案就是:(displaystylefrac{n^ncdot n-h(n)+ncdot (n-1)^n}{n^n})

    时间复杂度(O(Nlog N))

    参考代码

    ( ext{NTT})和多项式(ln)的部分省略了,自己贴板子吧。

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    const int MAXN=5e5;
    const int MOD=998244353;
    inline int mod1(int x){return x<MOD?x:x-MOD;}
    inline int mod2(int x){return x<0?x+MOD:x;}
    inline void add(int& x,int y){x=mod1(x+y);}
    inline void sub(int& x,int y){x=mod2(x-y);}
    inline int pow_mod(int x,int i){int y=1;while(i){if(i&1)y=(ll)y*x%MOD;x=(ll)x*x%MOD;i>>=1;}return y;}
    
    int fac[MAXN+5],ifac[MAXN+5];
    inline int comb(int n,int k){
    	if(n<k)return 0;
    	return (ll)fac[n]*ifac[k]%MOD*ifac[n-k]%MOD;
    }
    void facinit(int lim=MAXN){
    	fac[0]=1;
    	for(int i=1;i<=lim;++i)fac[i]=(ll)fac[i-1]*i%MOD;
    	ifac[lim]=pow_mod(fac[lim],MOD-2);
    	for(int i=lim-1;i>=0;--i)ifac[i]=(ll)ifac[i+1]*(i+1)%MOD;
    }
    
    int f[MAXN+5],g[MAXN+5],h[MAXN+5];
    
    int main() {
    	facinit();
    	
    	for(int i=1;i<=MAXN;++i){
    		g[i]=(ll)pow_mod(i,i)*ifac[i]%MOD;
    	}
    	g[0]=1;
    	Ln::main(g,f,MAXN+1);
    	Mul::main(g,f,h,MAXN+1);
    	for(int i=0;i<=MAXN;++i){
    		h[i]=(ll)h[i]*fac[i]%MOD;
    	}
    	int n;cin>>n;
    	for(int i=1;i<=n;++i){
    		int ans=h[i]%MOD;
    		int tot=pow_mod(i,i);
    		ans=mod2((ll)tot*i%MOD - ans);
    		ans=(ll)ans*pow_mod(tot,MOD-2)%MOD;
    		cout<<0<<" "<<ans<<" ";
    		int x=pow_mod(i-1,i);
    		int y=pow_mod(i,i-1);
    		x=(ll)x*pow_mod(y,MOD-2)%MOD;
    		add(ans,x);
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    Bw树:新硬件平台的B树(内存数据库中的b树索引)
    SQL Server 列存储索引强化
    SQL Server Column Store Indeses
    我了解的数据库事务复制
    [MySQL Reference Manual] 10 全球化
    [20141208]数据库复制并不会复制索引创建删除
    10个超赞的jQuery图片滑块动画
    推荐20款JavaScript框架给前端开发者
    7个华丽的基于Canvas的HTML5动画
    10个非常炫酷的jQuery相册动画赏析
  • 原文地址:https://www.cnblogs.com/dysyn1314/p/13436563.html
Copyright © 2011-2022 走看看