题目大意:$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)$。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=,mod=;
  4. #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
  5. #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
  6. #define MEM(x,v) memset(x,v,sizeof(x))
  7. inline int read(){
  8. char ch=getchar();int x=,f=;
  9. while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
  10. while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
  11. return f?-x:x;
  12. }
  13. int n,k,ans,kp[maxn],k1p[maxn],pr[maxn/],pl,ky[maxn],k1y[maxn],fac[maxn],invfac[maxn],tfac[maxn],tinv[maxn];
  14. bool vis[maxn];
  15. int qpow(int a,int b){
  16. int ans=;
  17. for(;b;b>>=,a=1ll*a*a%mod) if(b&) ans=1ll*ans*a%mod;
  18. return ans;
  19. }
  20. int kcalc(int x){
  21. if(x<=k+){
  22. int ans=1ll*ky[x]*fac[x-]%mod*fac[k-x+]%mod;
  23. if((k-x)&) return ans?mod-ans:;
  24. else return ans;
  25. }
  26. if(x>=mod) return (kcalc(mod-)+kcalc(x%mod))%mod;
  27. tfac[]=;
  28. FOR(i,,k+) tfac[i]=1ll*tfac[i-]*(x-i)%mod;
  29. tinv[k+]=qpow(tfac[k+],mod-);
  30. ROF(i,k+,) tinv[i]=1ll*tinv[i+]*(x-i-)%mod;
  31. FOR(i,,k+) tinv[i]=1ll*tinv[i]*tfac[i-]%mod;
  32. int ans=;
  33. FOR(i,,k+) ans=(ans+1ll*ky[i]*tfac[k+]%mod*tinv[i])%mod;
  34. return ans;
  35. }
  36. int k1calc(int x){
  37. if(x<=k+){
  38. int ans=1ll*k1y[x]*fac[x-]%mod*fac[k-x+]%mod;
  39. if((k-x)&) return ans;
  40. else return ans?mod-ans:;
  41. }
  42. if(x>=mod) return (k1calc(mod-)+k1calc(x%mod))%mod;
  43. tfac[]=;
  44. FOR(i,,k+) tfac[i]=1ll*tfac[i-]*(x-i)%mod;
  45. tinv[k+]=qpow(tfac[k+],mod-);
  46. ROF(i,k+,) tinv[i]=1ll*tinv[i+]*(x-i-)%mod;
  47. FOR(i,,k+) tinv[i]=1ll*tinv[i]*tfac[i-]%mod;
  48. int ans=;
  49. FOR(i,,k+) ans=(ans+1ll*k1y[i]*tfac[k+]%mod*tinv[i])%mod;
  50. return ans;
  51. }
  52. int main(){
  53. n=read();k=read();
  54. fac[]=;
  55. FOR(i,,k+) fac[i]=1ll*fac[i-]*i%mod;
  56. invfac[k+]=qpow(fac[k+],mod-);
  57. ROF(i,k+,) invfac[i]=1ll*invfac[i+]*(i+)%mod;
  58. kp[]=k1p[]=;
  59. FOR(i,,k+){
  60. if(!vis[i]){
  61. pr[++pl]=i;
  62. kp[i]=qpow(i,k);
  63. k1p[i]=qpow(i,k+);
  64. }
  65. FOR(j,,pl){
  66. if(i*pr[j]>k+) break;
  67. vis[i*pr[j]]=true;
  68. kp[i*pr[j]]=1ll*kp[i]*kp[pr[j]]%mod;
  69. k1p[i*pr[j]]=1ll*k1p[i]*k1p[pr[j]]%mod;
  70. if(i%pr[j]==) break;
  71. }
  72. }
  73. ky[]=k1y[]=;
  74. FOR(i,,k+) ky[i]=(ky[i-]+kp[i])%mod,k1y[i]=(k1y[i-]+k1p[i])%mod;
  75. FOR(i,,k+){
  76. ky[i]=1ll*ky[i]*invfac[i-]%mod*invfac[k-i+]%mod;
  77. if((k-i)&) ky[i]=ky[i]?mod-ky[i]:;
  78. k1y[i]=1ll*k1y[i]*invfac[i-]%mod*invfac[k-i+]%mod;
  79. if(!((k-i)&)) k1y[i]=k1y[i]?mod-k1y[i]:;
  80. }
  81. ans=*k1calc(n)%mod;
  82. ans=(ans-(2ll*n++qpow(,k))*kcalc(n)%mod+mod)%mod;
  83. ans=(ans+1ll*(*n+)*kcalc(*n)%mod)%mod;
  84. ans=(ans-k1calc(*n)+mod)%mod;
  85. ans=1ll*ans*qpow(n,mod-)%mod;
  86. printf("%d\n",ans);
  87. }

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……码出了数据结构题的感觉……)

  1. #define Orz_NaCly_Fish
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. typedef long long ll;
  5. const int maxn=,mod=;
  6. #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
  7. #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
  8. #define MEM(x,v) memset(x,v,sizeof(x))
  9. inline int read(){
  10. char ch=getchar();int x=,f=;
  11. while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
  12. while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
  13. return f?-x:x;
  14. }
  15. 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];
  16. char nstr[];
  17. bool vis[maxn];
  18. inline int add(int a,int b){return a+b<mod?a+b:a+b-mod;}
  19. inline int sub(int a,int b){return a<b?a-b+mod:a-b;}
  20. inline int mul(int a,int b){return 1ll*a*b%mod;}
  21. inline int qpow(int a,int b){
  22. int ans=;
  23. for(;b;b>>=,a=mul(a,a)) if(b&) ans=mul(ans,a);
  24. return ans;
  25. }
  26. int kcalc(int x){
  27. if(x<=k+){
  28. int ans=mul(mul(ky[x],fac[x]),fac[k-x+]);
  29. if(!((k-x)&)) return ans?mod-ans:;
  30. else return ans;
  31. }
  32. if(x==mod){
  33. tfac[]=;
  34. FOR(i,,k+) tfac[i]=mul(tfac[i-],x-i);
  35. tinv[k+]=qpow(tfac[k+],mod-);
  36. ROF(i,k,) tinv[i]=mul(tinv[i+],x-i-);
  37. FOR(i,,k+) tinv[i]=mul(tinv[i],tfac[i-]);
  38. int ans=;
  39. FOR(i,,k+) ans=add(ans,mul(mul(ky[i],tfac[k+]),tinv[i]));
  40. return ans;
  41. }
  42. tfac[]=x;
  43. FOR(i,,k+) tfac[i]=mul(tfac[i-],x-i);
  44. tinv[k+]=qpow(tfac[k+],mod-);
  45. ROF(i,k,) tinv[i]=mul(tinv[i+],x-i-);
  46. FOR(i,,k+) tinv[i]=mul(tinv[i],tfac[i-]);
  47. int ans=;
  48. FOR(i,,k+) ans=add(ans,mul(mul(ky[i],tfac[k+]),tinv[i]));
  49. return ans;
  50. }
  51. int k1calc(int x){
  52. if(x<=k+){
  53. int ans=mul(mul(k1y[x],fac[x]),fac[k-x+]);
  54. if((k-x)&) return ans?mod-ans:;
  55. else return ans;
  56. }
  57. if(x==mod){
  58. tfac[]=;
  59. FOR(i,,k+) tfac[i]=mul(tfac[i-],x-i);
  60. tinv[k+]=qpow(tfac[k+],mod-);
  61. ROF(i,k+,) tinv[i]=mul(tinv[i+],x-i-);
  62. FOR(i,,k+) tinv[i]=mul(tinv[i],tfac[i-]);
  63. int ans=;
  64. FOR(i,,k+) ans=add(ans,mul(mul(k1y[i],tfac[k+]),tinv[i]));
  65. return ans;
  66. }
  67. tfac[]=x;
  68. FOR(i,,k+) tfac[i]=mul(tfac[i-],x-i);
  69. tinv[k+]=qpow(tfac[k+],mod-);
  70. ROF(i,k+,) tinv[i]=mul(tinv[i+],x-i-);
  71. FOR(i,,k+) tinv[i]=mul(tinv[i],tfac[i-]);
  72. int ans=;
  73. FOR(i,,k+) ans=add(ans,mul(mul(k1y[i],tfac[k+]),tinv[i]));
  74. return ans;
  75. }
  76. void init(){
  77. fac[]=;
  78. FOR(i,,k+) fac[i]=mul(fac[i-],i);
  79. invfac[k+]=qpow(fac[k+],mod-);
  80. ROF(i,k+,) invfac[i]=mul(invfac[i+],i+);
  81. kp[]=k1p[]=;
  82. FOR(i,,k+){
  83. if(!vis[i]){
  84. pr[++pl]=i;
  85. kp[i]=qpow(i,k);
  86. k1p[i]=qpow(i,k+);
  87. }
  88. FOR(j,,pl){
  89. if(i*pr[j]>k+) break;
  90. vis[i*pr[j]]=true;
  91. kp[i*pr[j]]=mul(kp[i],kp[pr[j]]);
  92. k1p[i*pr[j]]=mul(k1p[i],k1p[pr[j]]);
  93. if(i%pr[j]==) break;
  94. }
  95. }
  96. ky[]=k1y[]=;
  97. FOR(i,,k+) ky[i]=add(ky[i-],kp[i]),k1y[i]=add(k1y[i-],k1p[i]);
  98. FOR(i,,k+){
  99. ky[i]=mul(mul(ky[i],invfac[i]),invfac[k-i+]);
  100. if(!((k-i)&)) ky[i]=ky[i]?mod-ky[i]:;
  101. k1y[i]=mul(mul(k1y[i],invfac[i]),invfac[k-i+]);
  102. if((k-i)&) k1y[i]=k1y[i]?mod-k1y[i]:;
  103. }
  104. }
  105. int main(){
  106. scanf("%s",nstr+);k=read();
  107. len=strlen(nstr+);
  108. init();
  109. FOR(i,,len){
  110. ll tmp=10ll*nmod+nstr[i]-'';
  111. ndiv=add(mul(ndiv,),tmp/mod);
  112. nmod=tmp%mod;
  113. }
  114. if(nmod){
  115. int ktmp=kcalc(mod-),k1tmp=k1calc(mod-);
  116. int krem=kcalc(nmod),k1rem=k1calc(nmod);
  117. int kans=add(mul(ndiv,ktmp),krem),k1ans=add(mul(ndiv,k1tmp),k1rem);
  118. ans=mul(,k1ans);
  119. ans=sub(ans,mul(add(add(mul(nmod,),),qpow(,k)),kans));
  120. krem=kcalc(mul(nmod,)),k1rem=k1calc(mul(nmod,));
  121. kans=add(mul(add(mul(ndiv,),nmod>mod/),ktmp),krem),k1ans=add(mul(add(mul(ndiv,),nmod>mod/),k1tmp),k1rem);
  122. ans=add(ans,mul(*nmod+,kans));
  123. ans=sub(ans,k1ans);
  124. ans=mul(ans,qpow(nmod,mod-));
  125. printf("%d\n",ans);
  126. }
  127. else{
  128. int kans=kcalc(mod),k1ans=k1calc(mod);
  129. ans=mul(,k1ans);
  130. ans=sub(ans,mul(add(,qpow(,k)),kans));
  131. ans=add(ans,mul(,kans));
  132. ans=sub(ans,mul(,k1ans));
  133. printf("%d\n",ans);
  134. }
  135. }

洛谷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. QQ音乐2019客户端-获取任意歌单完整歌曲列表和下载音乐文件方法

    步骤 1.在web网站上搜搜任意歌单 https://y.qq.com/#type=index/ 例如:中国好声音4.5.6.7.8季 打开后显示网址:  https://y.qq.com/n/yqq ...

  2. redis命令之 ----Hash(哈希表)

    HDEL HDEL key field [field ...] 删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略. HEXISTS HEXISTS key field 查看哈希表 key  ...

  3. LeetCode Contest 166

    LeetCode Contest 166 第一次知道LeetCode 也有比赛. 很久没有打过这种线上的比赛,很激动. 直接写题解吧 第一题 很弱智 class Solution { public: ...

  4. MySQL优化常见Extra分析——慢查询优化

    数据准备: create table user ( id int primary key, name ), sex ), index(name) )engine=innodb; 数据说明:用户表:id ...

  5. [Docker] Win10中安装Docker并运行Nginx镜像

    一.安装Docker 进入官网:https://www.docker.com/products/docker-desktop 可能需要先注册登录,很简单的. 点击 Download Desktop f ...

  6. Java匹马行天下之学编程的起点——走进编程的殿堂

    学编程的起点——走进编程的殿堂 前言: 知其然,知其所以然,努力固然重要,但是思维的提升会让你事半功倍,我会用我花费时间换来的“思维”带更多的朋友入门,让你们明明白白学编程,学编程,不迷茫. 转变思维 ...

  7. 高性能TcpServer(C#) - 3.命令通道(处理:掉包,粘包,垃圾包)

    高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...

  8. 消息服务dubbo接口性能压测性能优化案例

    最近项目中的消息服务做了运营商的改动,导致这个服务做了重新开发 压测脚本如下: 开启200线程压测: tps只有200-300之间,平均耗时在700ms左右 开启500线程压测 500并发压测,发现平 ...

  9. 【新手篇】搭建DCN漏洞靶机及简单的SQL手工注入

    很多新手小白入门后发现想要学好“网安”技术,除了掌握基础理论知识,更需要经常模拟不同的漏洞环境,但是如果使用外网服务器练习,会存在一定风险,因此能够搭建一个本地的模拟环境去测试漏洞将是一个不错的方案. ...

  10. 【设计模式】Prototype

    前言 这篇讲设计模式的部分相对较少.Prototype设计模式,它提供一种复制对象的思路.使用Prototype就可以在不需要了解类结构的前提下,复制一个现有对象.写了一个代码片段,讲解使用Objec ...