首页 > 其他 > 详细

#拉格朗日插值,线性筛#洛谷 5442 【XR-2】约定 (加强版)

时间:2020-06-03 21:43:57      阅读:54      评论:0      收藏:0      [点我收藏+]

题目

一个\(n\)个点的完全图,
\(i\)个点到第\(j\)个点的边权是\((i+j)^k\),
现在把这个完全图变成一棵树,
求这棵树边权和的期望值
\((n\leq 10^{10000},k\leq 10^7,mod=998244353)\)


分析

因为\(n\)个结点的完全图的生成树个数为\(n^{n-2}\)
每条边在生成树中出现的次数是\(\frac{(n-1)n^{n-2}}{\frac{n(n-1)}{2}}=2n^{n-3}\)
所以应该

\[ans=\frac{2}{n}\sum_{i=1}^n\sum_{j=i+1}^n(i+j)^k \]

考虑差分

\[ans_n-ans_{n-1}=\sum_{i=n+1}^{2n-1}i^k \]

对于单个正整数幂,因为它是积性函数,所以可以线性筛

后面这个东西脑补一下应该是一个\(k+2\)次多项式,

可以通过拉格朗日插值实现,因为这些值是连续的,所以可以\(O(k)\)实现

弱化版讲完了,由于\(n\)在模意义下可能为0,所以要特判

\(998244353^2\)作新模数,如果最后\(n\)在模意义下不存在逆元,

可以证明答案是998244353的倍数,那么直接除掉就可以了

不过常数超级大,比多项式做法慢多了


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef long long lll; typedef long double ld;
const lll mod=996491788296388609ll,N=2e7+11,rmod=998244353;
lll n,f[N],fac[N>>1],jc[N>>1],inv[N>>1]; int k,lim,Cnt,prime[1300001];
inline lll mol(lll a,lll b){
    rr lll c=(ld)a*b/mod,ans=a*b-c*mod;
    ans=ans<0?ans+mod:(ans>=mod?ans-mod:ans);
    return ans;
}
inline lll mo1(lll x,lll y){return x+y>=mod?x+y-mod:x+y;}
inline lll mo2(lll x,lll y){return x<y?x-y+mod:x-y;}
inline lll ksm(lll x,lll y){
    rr lll ans=1;
    for (;y;y>>=1,x=mol(x,x))
        if (y&1) ans=mol(ans,x);
    return ans;
}
inline lll answ(){
    jc[0]=jc[1]=fac[0]=1;
    for (rr int i=2;i<=lim;++i) jc[i]=mol(jc[i-1],i);
    rr lll prod=1,ans=0;
    for (rr int i=1;i<=lim;++i){
        prod=mol(prod,n-i);
        inv[i]=fac[i]=mol(mol(jc[i-1],jc[lim-i]),n-i);
    }
    for (rr int i=1;i<=lim;++i) fac[i]=mol(fac[i],fac[i-1]);
	fac[lim]=ksm(fac[lim],mod-2);
    for (rr int i=lim;i;--i){
        rr lll t=inv[i];
        inv[i]=mol(fac[i-1],fac[i]),
        fac[i-1]=mol(t,fac[i]);
    }
    for (rr int i=1;i<=lim;++i){
        rr lll t=mol(mol(f[i],prod),inv[i]);
        ans=mo1(ans,((lim^i)&1)?mod-t:t);
    }
    return ans;
}
inline signed rksm(int x,int y){
	rr int ans=1;
	for (;y;y>>=1,x=1ll*x*x%rmod)
	    if (y&1) ans=1ll*ans*x%rmod;
	return ans; 
}
signed main(){
	rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) n=(n*10+c-48)%rmod,c=getchar();
    scanf("%d",&k),f[1]=1,n=n<1?n+rmod:n,lim=(n<k+2?n+1:k+3)<<1;
    for (rr int i=2;i<=lim;++i){
        if (!f[i]) f[prime[++Cnt]=i]=ksm(i,k);
        for (rr int j=1;j<=Cnt&&prime[j]<=lim/i;++j){
            f[i*prime[j]]=mol(f[i],f[prime[j]]);
            if (i%prime[j]==0) break;
        }
    }
    for (rr int i=2;i<=lim;++i) f[i]=mo1(f[i],f[i-1]); lim>>=1;
    for (rr int i=0;i<lim;++i) f[i+1]=mo1(f[i],mo2(f[i<<1|1],f[i+1]));
    rr lll ans=n<=lim?f[n]:answ(); ans=mo1(ans,ans);
    if (n%rmod) printf("%lld",ans%rmod*rksm(n,rmod-2)%rmod);
        else printf("%lld",ans/rmod);
    return 0;
}

#拉格朗日插值,线性筛#洛谷 5442 【XR-2】约定 (加强版)

原文:https://www.cnblogs.com/Spare-No-Effort/p/13040090.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!