洛谷P5437/5442 约定(概率期望,拉格朗日插值,自然数幂)
题目大意:$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 约定(概率期望,拉格朗日插值,自然数幂)的更多相关文章
- 洛谷 P7116 - [NOIP2020] 微信步数(拉格朗日插值)
洛谷题面传送门 我竟然独立切掉了这道题!incredible! 纪念我逝去的一上午(NOIP 总时长 4.5h,这题做了我整整 4.5h) 首先讲一下现场我想的 80 分的做法,虽然最后挂成了 65 ...
- 洛谷P4593 [TJOI2018]教科书般的亵渎(拉格朗日插值)
题意 题目链接 Sol 打出暴力不难发现时间复杂度的瓶颈在于求\(\sum_{i = 1}^n i^k\) 老祖宗告诉我们,这东西是个\(k\)次多项式,插一插就行了 上面的是\(O(Tk^2)\)的 ...
- 洛谷 P2473 [SCOI2008]奖励关 ( 期望DP )
题目链接 题意 : 中文题.点链接 分析 : 第一道有关概率期望的DP 有个大部分情况下通用的结论 概率正推.期望反推 原因不明.其实是没有查到较好的解释 这题由于有一些取物品的先决条件在这里 而且观 ...
- 洛谷P5158 【模板】多项式快速插值
题面 传送门 前置芝士 拉格朗日插值,多项式多点求值 题解 首先根据拉格朗日插值公式我们可以暴力\(O(n^2)\)插出这个多项式,然而这显然是\(gg\)的 那么看看怎么优化,先来看一看拉格朗日插值 ...
- 洛谷P1654 OSU!_概率与期望
Code: #include<cstdio> #include<algorithm> using namespace std; const int maxn = 1000000 ...
- 洛谷P4561 [JXOI2018]排序问题(二分 期望)
题意 题目链接 Sol 首先一种方案的期望等于它一次排好的概率的倒数. 一次排好的概率是个数数题,他等于一次排好的方案除以总方案,也就是\(\frac{\prod cnt_{a_i}!}{(n+m)! ...
- 洛谷P1850 换教室 [noip2016] 期望dp
正解:期望dp 解题报告: 哇我发现我期望这块真的布星,可能在刷了点儿NOIp之后会去搞一波期望dp的题...感觉连基础都没有打扎实?基础概念都布星! 好那先把这题理顺了嗷qwq 首先我们看到期望就会 ...
- 洛谷P3830 [SHOI2012]随机树(期望dp)
题面 luogu 题解 第一问: 设\(f[i]\)表示\(i\)步操作后,平均深度期望 \(f[i] = \frac {f[i - 1] * (i - 1)+f[i-1]+2}{i}=f[i-1]+ ...
- 洛谷 P3239 [HNOI2015]亚瑟王(期望dp)
题面 luogu 题解 一道复杂的期望\(dp\) 思路来源:__stdcall 容易想到,只要把每张牌打出的概率算出来就可以求出\(ans\) 设\(fp[i]\)表示把第\(i\)张牌打出来的概率 ...
随机推荐
- QQ音乐2019客户端-获取任意歌单完整歌曲列表和下载音乐文件方法
步骤 1.在web网站上搜搜任意歌单 https://y.qq.com/#type=index/ 例如:中国好声音4.5.6.7.8季 打开后显示网址: https://y.qq.com/n/yqq ...
- redis命令之 ----Hash(哈希表)
HDEL HDEL key field [field ...] 删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略. HEXISTS HEXISTS key field 查看哈希表 key ...
- LeetCode Contest 166
LeetCode Contest 166 第一次知道LeetCode 也有比赛. 很久没有打过这种线上的比赛,很激动. 直接写题解吧 第一题 很弱智 class Solution { public: ...
- MySQL优化常见Extra分析——慢查询优化
数据准备: create table user ( id int primary key, name ), sex ), index(name) )engine=innodb; 数据说明:用户表:id ...
- [Docker] Win10中安装Docker并运行Nginx镜像
一.安装Docker 进入官网:https://www.docker.com/products/docker-desktop 可能需要先注册登录,很简单的. 点击 Download Desktop f ...
- Java匹马行天下之学编程的起点——走进编程的殿堂
学编程的起点——走进编程的殿堂 前言: 知其然,知其所以然,努力固然重要,但是思维的提升会让你事半功倍,我会用我花费时间换来的“思维”带更多的朋友入门,让你们明明白白学编程,学编程,不迷茫. 转变思维 ...
- 高性能TcpServer(C#) - 3.命令通道(处理:掉包,粘包,垃圾包)
高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...
- 消息服务dubbo接口性能压测性能优化案例
最近项目中的消息服务做了运营商的改动,导致这个服务做了重新开发 压测脚本如下: 开启200线程压测: tps只有200-300之间,平均耗时在700ms左右 开启500线程压测 500并发压测,发现平 ...
- 【新手篇】搭建DCN漏洞靶机及简单的SQL手工注入
很多新手小白入门后发现想要学好“网安”技术,除了掌握基础理论知识,更需要经常模拟不同的漏洞环境,但是如果使用外网服务器练习,会存在一定风险,因此能够搭建一个本地的模拟环境去测试漏洞将是一个不错的方案. ...
- 【设计模式】Prototype
前言 这篇讲设计模式的部分相对较少.Prototype设计模式,它提供一种复制对象的思路.使用Prototype就可以在不需要了解类结构的前提下,复制一个现有对象.写了一个代码片段,讲解使用Objec ...