题目大意:$n$ 个点的完全图,点 $i$ 和点 $j$ 的边权为 $(i+j)^k$。随机一个生成树,问这个生成树边权和的期望对 $998244353$ 取模的值。

对于P5437:$1\le n\le 998244352,1\le k\le 10^7$。

对于P5442:$1\le n\le 10^4,\le k\le 10^7$。


其实也是一道比较简单的题。(所以就应该把这题和上一道原题调个位置)

考虑一条边在生成树中出现的概率,由于一共有 $\dfrac{n(n-1)}{2}$ 条边,一个生成树有 $n-1$ 条边,而每条边的概率相等,所以为 $\dfrac{2}{n}$。

那么开始推式子:(注:第三步是枚举 $i+j$)

$$\dfrac{2}{n}\sum\limits_{i=1}^n\sum\limits_{j=i+1}^n(i+j)^k$$$$\dfrac{1}{n}(\sum\limits_{i=1}^n\sum\limits_{j=1}^n(i+j)^k-\sum\limits^n_{i=1}(i+i)^k)$$

$$\dfrac{1}{n}(\sum\limits_{s=1}^{2n}s^k\min(s-1,2n+1-s)-2^k\sum\limits^n_{i=1}i^k)$$

$$\dfrac{1}{n}(\sum\limits_{s=1}^{n}s^k(s-1)+\sum\limits_{s=n+1}^{2n}s^k(2n+1-s)-2^k\sum\limits^n_{i=1}i^k)$$

$$\dfrac{1}{n}(\sum\limits_{s=1}^{n}s^{k+1}-\sum\limits_{s=1}^{n}s^{k}+(2n+1)\sum\limits_{s=n+1}^{2n}s^k-\sum\limits_{s=n+1}^{2n}s^{k+1}-2^{k}\sum\limits^n_{i=1}i^k)$$

$$\dfrac{1}{n}(2\sum\limits_{i=1}^{n}i^{k+1}-(2n+2+2^k)\sum\limits_{i=1}^{n}i^{k}+(2n+1)\sum\limits_{i=1}^{2n}i^k-\sum\limits_{i=1}^{2n}i^{k+1})$$

现在问题就是求 $f(n)=\sum\limits_{i=1}^ni^k$ 了。

由于 $f(n)-f(n-1)=n^k$,$f$ 的差值是个 $k$ 次多项式,所以 $f$ 是个 $k+1$ 次多项式。

那么可以拉格朗日插值。(以下内容的代码实现细节比较多,注意要控制复杂度不带 $\log$)

取 $k+2$ 个点为 $1$ 到 $k+2$,发现点值 $y_i$ 可以 $O(k)$ 计算。($y_i=y_{i-1}+i^k$ 不能直接快速幂,不然带 $\log$。可以用欧拉筛筛出所有 $k$ 次方)

$$f(n)=\sum\limits_{i=1}^{k+2}y_i\dfrac{\prod\limits^{k+2}_{j=1,j\ne i}(n-x_j)}{\prod\limits^{k+2}_{j=1,j\ne i}(x_i-x_j)}$$

这样拉格朗日插值公式中的分母就是两个阶乘相乘的形式,可以 $O(1)$。(预处理要注意控制复杂度)

代入一个数算时,先特判 $n\ge mod$(因为会调用到 $f(2n)$),此时 $f(n)=\lfloor\dfrac{n}{mod}\rfloor f(mod-1)+f(n\%mod)$。

否则先算出 $fac=\prod\limits_{i=1}^{k+2}(n-i)$。同时预处理出所有 $n-i$ 的逆元 $inv_i$。(不要一个个快速幂算,复杂度错的。要用 $O(k+\log)$ 的方式)

此时就有:

$$f(n)=\sum\limits_{i=1}^{k+2}y_i\dfrac{fac\times inv_i}{(i-1)!(k-i+2)!(-1)^{k-i+2}}$$

已经可以 $O(k)$ 计算了。

时间复杂度 $O(k+\log)$。

#include<bits/stdc++.h>
using namespace std;
const int maxn=,mod=;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
char ch=getchar();int x=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
int n,k,ans,kp[maxn],k1p[maxn],pr[maxn/],pl,ky[maxn],k1y[maxn],fac[maxn],invfac[maxn],tfac[maxn],tinv[maxn];
bool vis[maxn];
int qpow(int a,int b){
int ans=;
for(;b;b>>=,a=1ll*a*a%mod) if(b&) ans=1ll*ans*a%mod;
return ans;
}
int kcalc(int x){
if(x<=k+){
int ans=1ll*ky[x]*fac[x-]%mod*fac[k-x+]%mod;
if((k-x)&) return ans?mod-ans:;
else return ans;
}
if(x>=mod) return (kcalc(mod-)+kcalc(x%mod))%mod;
tfac[]=;
FOR(i,,k+) tfac[i]=1ll*tfac[i-]*(x-i)%mod;
tinv[k+]=qpow(tfac[k+],mod-);
ROF(i,k+,) tinv[i]=1ll*tinv[i+]*(x-i-)%mod;
FOR(i,,k+) tinv[i]=1ll*tinv[i]*tfac[i-]%mod;
int ans=;
FOR(i,,k+) ans=(ans+1ll*ky[i]*tfac[k+]%mod*tinv[i])%mod;
return ans;
}
int k1calc(int x){
if(x<=k+){
int ans=1ll*k1y[x]*fac[x-]%mod*fac[k-x+]%mod;
if((k-x)&) return ans;
else return ans?mod-ans:;
}
if(x>=mod) return (k1calc(mod-)+k1calc(x%mod))%mod;
tfac[]=;
FOR(i,,k+) tfac[i]=1ll*tfac[i-]*(x-i)%mod;
tinv[k+]=qpow(tfac[k+],mod-);
ROF(i,k+,) tinv[i]=1ll*tinv[i+]*(x-i-)%mod;
FOR(i,,k+) tinv[i]=1ll*tinv[i]*tfac[i-]%mod;
int ans=;
FOR(i,,k+) ans=(ans+1ll*k1y[i]*tfac[k+]%mod*tinv[i])%mod;
return ans;
}
int main(){
n=read();k=read();
fac[]=;
FOR(i,,k+) fac[i]=1ll*fac[i-]*i%mod;
invfac[k+]=qpow(fac[k+],mod-);
ROF(i,k+,) invfac[i]=1ll*invfac[i+]*(i+)%mod;
kp[]=k1p[]=;
FOR(i,,k+){
if(!vis[i]){
pr[++pl]=i;
kp[i]=qpow(i,k);
k1p[i]=qpow(i,k+);
}
FOR(j,,pl){
if(i*pr[j]>k+) break;
vis[i*pr[j]]=true;
kp[i*pr[j]]=1ll*kp[i]*kp[pr[j]]%mod;
k1p[i*pr[j]]=1ll*k1p[i]*k1p[pr[j]]%mod;
if(i%pr[j]==) break;
}
}
ky[]=k1y[]=;
FOR(i,,k+) ky[i]=(ky[i-]+kp[i])%mod,k1y[i]=(k1y[i-]+k1p[i])%mod;
FOR(i,,k+){
ky[i]=1ll*ky[i]*invfac[i-]%mod*invfac[k-i+]%mod;
if((k-i)&) ky[i]=ky[i]?mod-ky[i]:;
k1y[i]=1ll*k1y[i]*invfac[i-]%mod*invfac[k-i+]%mod;
if(!((k-i)&)) k1y[i]=k1y[i]?mod-k1y[i]:;
}
ans=*k1calc(n)%mod;
ans=(ans-(2ll*n++qpow(,k))*kcalc(n)%mod+mod)%mod;
ans=(ans+1ll*(*n+)*kcalc(*n)%mod)%mod;
ans=(ans-k1calc(*n)+mod)%mod;
ans=1ll*ans*qpow(n,mod-)%mod;
printf("%d\n",ans);
}

upd:

以上是原版的做法。

毒瘤的神鱼又加强了这题……然后就……让我来做……

受宠若惊呢QwQ

不过真没想到自己也能想到加强版正解。


先考虑 $n$ 不为 $998244353$(以下简写为 $p$)的倍数。(因为式子前面有个 $\dfrac{1}{n}$,可能没有逆元)

那么 $\sum\limits_{i=1}^ni^k=\lfloor\dfrac{n}{p}\rfloor\sum\limits_{i=1}^{p-1}i^k+\sum\limits_{i=1}^{n\bmod p}i^k$。

写个高精除低精就没了。

然后考虑 $n$ 是 $p$ 的倍数。

$\sum\limits_{i=1}^ni^k=\dfrac{n}{p}\sum\limits_{i=1}^pi^k$。

此时原式:

$$\dfrac{1}{n}(\dots\sum\limits^n_{i=1}i^k+\dots\sum\limits^{2n}_{i=1}i^k)$$

$$\dfrac{1}{n}(\dfrac{n}{p}\dots\sum\limits^{p-1}_{i=1}i^k+2\dfrac{n}{p}\dots\sum\limits^{p-1}_{i=1}i^k)$$

$$\dfrac{1}{p}\dots\sum\limits^{p-1}_{i=1}i^k+\dfrac{2}{p}\dots\sum\limits^{p-1}_{i=1}i^k$$

此处取点值为 $0$ 到 $k+1$ 而不是上文中的 $1$ 到 $k+2$。

观察拉格朗日插值的式子,分子是有个 $x-x_j$ 的。那么当 $i=0$ 时,$y_i=0$,是 $p$ 的倍数。当 $i\ne 0$ 时,$x-x_0=x=p$,是 $p$ 的倍数。

那么只需要在分子中不乘上那个 $x-x_0=p$ 即可。就相当于求出了 $\frac{\sum\limits_{i=1}^pi^k}{p}$。

那么就做完了。

时间复杂度 $O(k+\log n)$。

(神鱼太毒瘤了……一道数论题我码了3.8K……码出了数据结构题的感觉……)

#define Orz_NaCly_Fish
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=,mod=;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
char ch=getchar();int x=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
int ndiv,nmod,k,ans,len,kp[maxn],k1p[maxn],pr[maxn/],pl,ky[maxn],k1y[maxn],fac[maxn],invfac[maxn],tfac[maxn],tinv[maxn];
char nstr[];
bool vis[maxn];
inline int add(int a,int b){return a+b<mod?a+b:a+b-mod;}
inline int sub(int a,int b){return a<b?a-b+mod:a-b;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline int qpow(int a,int b){
int ans=;
for(;b;b>>=,a=mul(a,a)) if(b&) ans=mul(ans,a);
return ans;
}
int kcalc(int x){
if(x<=k+){
int ans=mul(mul(ky[x],fac[x]),fac[k-x+]);
if(!((k-x)&)) return ans?mod-ans:;
else return ans;
}
if(x==mod){
tfac[]=;
FOR(i,,k+) tfac[i]=mul(tfac[i-],x-i);
tinv[k+]=qpow(tfac[k+],mod-);
ROF(i,k,) tinv[i]=mul(tinv[i+],x-i-);
FOR(i,,k+) tinv[i]=mul(tinv[i],tfac[i-]);
int ans=;
FOR(i,,k+) ans=add(ans,mul(mul(ky[i],tfac[k+]),tinv[i]));
return ans;
}
tfac[]=x;
FOR(i,,k+) tfac[i]=mul(tfac[i-],x-i);
tinv[k+]=qpow(tfac[k+],mod-);
ROF(i,k,) tinv[i]=mul(tinv[i+],x-i-);
FOR(i,,k+) tinv[i]=mul(tinv[i],tfac[i-]);
int ans=;
FOR(i,,k+) ans=add(ans,mul(mul(ky[i],tfac[k+]),tinv[i]));
return ans;
}
int k1calc(int x){
if(x<=k+){
int ans=mul(mul(k1y[x],fac[x]),fac[k-x+]);
if((k-x)&) return ans?mod-ans:;
else return ans;
}
if(x==mod){
tfac[]=;
FOR(i,,k+) tfac[i]=mul(tfac[i-],x-i);
tinv[k+]=qpow(tfac[k+],mod-);
ROF(i,k+,) tinv[i]=mul(tinv[i+],x-i-);
FOR(i,,k+) tinv[i]=mul(tinv[i],tfac[i-]);
int ans=;
FOR(i,,k+) ans=add(ans,mul(mul(k1y[i],tfac[k+]),tinv[i]));
return ans;
}
tfac[]=x;
FOR(i,,k+) tfac[i]=mul(tfac[i-],x-i);
tinv[k+]=qpow(tfac[k+],mod-);
ROF(i,k+,) tinv[i]=mul(tinv[i+],x-i-);
FOR(i,,k+) tinv[i]=mul(tinv[i],tfac[i-]);
int ans=;
FOR(i,,k+) ans=add(ans,mul(mul(k1y[i],tfac[k+]),tinv[i]));
return ans;
}
void init(){
fac[]=;
FOR(i,,k+) fac[i]=mul(fac[i-],i);
invfac[k+]=qpow(fac[k+],mod-);
ROF(i,k+,) invfac[i]=mul(invfac[i+],i+);
kp[]=k1p[]=;
FOR(i,,k+){
if(!vis[i]){
pr[++pl]=i;
kp[i]=qpow(i,k);
k1p[i]=qpow(i,k+);
}
FOR(j,,pl){
if(i*pr[j]>k+) break;
vis[i*pr[j]]=true;
kp[i*pr[j]]=mul(kp[i],kp[pr[j]]);
k1p[i*pr[j]]=mul(k1p[i],k1p[pr[j]]);
if(i%pr[j]==) break;
}
}
ky[]=k1y[]=;
FOR(i,,k+) ky[i]=add(ky[i-],kp[i]),k1y[i]=add(k1y[i-],k1p[i]);
FOR(i,,k+){
ky[i]=mul(mul(ky[i],invfac[i]),invfac[k-i+]);
if(!((k-i)&)) ky[i]=ky[i]?mod-ky[i]:;
k1y[i]=mul(mul(k1y[i],invfac[i]),invfac[k-i+]);
if((k-i)&) k1y[i]=k1y[i]?mod-k1y[i]:;
}
}
int main(){
scanf("%s",nstr+);k=read();
len=strlen(nstr+);
init();
FOR(i,,len){
ll tmp=10ll*nmod+nstr[i]-'';
ndiv=add(mul(ndiv,),tmp/mod);
nmod=tmp%mod;
}
if(nmod){
int ktmp=kcalc(mod-),k1tmp=k1calc(mod-);
int krem=kcalc(nmod),k1rem=k1calc(nmod);
int kans=add(mul(ndiv,ktmp),krem),k1ans=add(mul(ndiv,k1tmp),k1rem);
ans=mul(,k1ans);
ans=sub(ans,mul(add(add(mul(nmod,),),qpow(,k)),kans));
krem=kcalc(mul(nmod,)),k1rem=k1calc(mul(nmod,));
kans=add(mul(add(mul(ndiv,),nmod>mod/),ktmp),krem),k1ans=add(mul(add(mul(ndiv,),nmod>mod/),k1tmp),k1rem);
ans=add(ans,mul(*nmod+,kans));
ans=sub(ans,k1ans);
ans=mul(ans,qpow(nmod,mod-));
printf("%d\n",ans);
}
else{
int kans=kcalc(mod),k1ans=k1calc(mod);
ans=mul(,k1ans);
ans=sub(ans,mul(add(,qpow(,k)),kans));
ans=add(ans,mul(,kans));
ans=sub(ans,mul(,k1ans));
printf("%d\n",ans);
}
}

洛谷P5437/5442 约定(概率期望,拉格朗日插值,自然数幂)的更多相关文章

  1. 洛谷 P7116 - [NOIP2020] 微信步数(拉格朗日插值)

    洛谷题面传送门 我竟然独立切掉了这道题!incredible! 纪念我逝去的一上午(NOIP 总时长 4.5h,这题做了我整整 4.5h) 首先讲一下现场我想的 80 分的做法,虽然最后挂成了 65 ...

  2. 洛谷P4593 [TJOI2018]教科书般的亵渎(拉格朗日插值)

    题意 题目链接 Sol 打出暴力不难发现时间复杂度的瓶颈在于求\(\sum_{i = 1}^n i^k\) 老祖宗告诉我们,这东西是个\(k\)次多项式,插一插就行了 上面的是\(O(Tk^2)\)的 ...

  3. 洛谷 P2473 [SCOI2008]奖励关 ( 期望DP )

    题目链接 题意 : 中文题.点链接 分析 : 第一道有关概率期望的DP 有个大部分情况下通用的结论 概率正推.期望反推 原因不明.其实是没有查到较好的解释 这题由于有一些取物品的先决条件在这里 而且观 ...

  4. 洛谷P5158 【模板】多项式快速插值

    题面 传送门 前置芝士 拉格朗日插值,多项式多点求值 题解 首先根据拉格朗日插值公式我们可以暴力\(O(n^2)\)插出这个多项式,然而这显然是\(gg\)的 那么看看怎么优化,先来看一看拉格朗日插值 ...

  5. 洛谷P1654 OSU!_概率与期望

    Code: #include<cstdio> #include<algorithm> using namespace std; const int maxn = 1000000 ...

  6. 洛谷P4561 [JXOI2018]排序问题(二分 期望)

    题意 题目链接 Sol 首先一种方案的期望等于它一次排好的概率的倒数. 一次排好的概率是个数数题,他等于一次排好的方案除以总方案,也就是\(\frac{\prod cnt_{a_i}!}{(n+m)! ...

  7. 洛谷P1850 换教室 [noip2016] 期望dp

    正解:期望dp 解题报告: 哇我发现我期望这块真的布星,可能在刷了点儿NOIp之后会去搞一波期望dp的题...感觉连基础都没有打扎实?基础概念都布星! 好那先把这题理顺了嗷qwq 首先我们看到期望就会 ...

  8. 洛谷P3830 [SHOI2012]随机树(期望dp)

    题面 luogu 题解 第一问: 设\(f[i]\)表示\(i\)步操作后,平均深度期望 \(f[i] = \frac {f[i - 1] * (i - 1)+f[i-1]+2}{i}=f[i-1]+ ...

  9. 洛谷 P3239 [HNOI2015]亚瑟王(期望dp)

    题面 luogu 题解 一道复杂的期望\(dp\) 思路来源:__stdcall 容易想到,只要把每张牌打出的概率算出来就可以求出\(ans\) 设\(fp[i]\)表示把第\(i\)张牌打出来的概率 ...

随机推荐

  1. (三十三)golang--面向对象之继承

    继承可以解决代码复用: 实现:只需要在结构体中嵌套一个匿名结构体: 结构体可以使用匿名结构体中所有字段核方法:无论是大写还是小写: 可以简化访问匿名结构体中的属性和方法: 当该结构体和匿名结构体有相同 ...

  2. 解决 Ubuntu16.04 + opencv4.1 源码编译错误 Makefile:160: recipe for target 'all' failed

    最近源码编译 opencv,出现下面的错误 [ %] Built target opencv_dnn Makefile:: recipe for target 'all' failed google ...

  3. Tensorflow源码解析2 -- 前后端连接的桥梁 - Session

    Session概述 1. Session是TensorFlow前后端连接的桥梁.用户利用session使得client能够与master的执行引擎建立连接,并通过session.run()来触发一次计 ...

  4. Reids Lua 模糊查询所有key 及 相对应的集合总数

    Redis 使用 Lua 模糊查询所有key 及 相对应的集合总数 .Net 4.5.1 需要引入:    StackExchange.Redis  (测试用的 1.2.4.0) 方法一: 优点:原子 ...

  5. 镭神激光雷达对于Autoware的适配

    1. 前言 我们的自动驾驶采用镭神激光雷达,在使用Autoware的时候,需要对镭神激光雷达的底层驱动,进行一些改变以适配Autoware. 2. 修改 (1)首先修改lslidar_c32.laun ...

  6. Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(二)

    接着上一篇 直接贴代码了: using System; using System.Collections.Generic; using System.Data.Entity; using System ...

  7. K8S集群集成harbor(1.9.3)服务并配置HTTPS

    一.简介 简介请参考:https://www.cnblogs.com/panwenbin-logs/p/10218099.html 二.安装Harbor主机环境及安装要求 主机环境: OS: Cent ...

  8. 【题解】ADAGRAFT - Ada and Graft [SP33331]

    [题解]ADAGRAFT - Ada and Graft [SP33331] 传送门:\(\text{Ada and Graft}\) \(\text{[SP33331]}\) [题目描述] 给出一颗 ...

  9. Windows 任务调度程序定时执行Python脚本

    Windows 任务调度程序(Task Scheduler)可以定时执行程序,本文分享使用Task Scheduler定时执行Python脚本的两种方法. 在控制面版->管理员工具中打开 Tas ...

  10. Logstash:多个配置文件(conf)

    Logstash:多个配置文件(conf) 对于多个配置的处理方法,有多个处理方法: 多个pipeline 一个pipleline处理多个配置文件 一个pipeline含有一个逻辑的数据流,它从inp ...