专栏文章
南京夜无电波讯号·题解
题解参与者 3已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @min48ii4
- 此快照首次捕获于
- 2025/12/01 20:18 3 个月前
- 此快照最后确认于
- 2025/12/01 20:18 3 个月前
存在比较直接的组合意义优化做法,不过应喜欢的人的要求,但是这里也介绍一下期望做法。
先定义一些东西,
组合做法的基本思路是拆贡献,分别对每个节点计算它取到某个 时的方案数,然后再累加起来。
本题考察的核心在于 的那个指数,而在组合做法中变为了无足轻重、画蛇添足的败笔,出题人需要好好反思,但这并不意味着期望做法没有思维启发性。
在期望做法的视角下, 的那个指数就变得比较难以处理,于是想到求解整体的变化量 ,再递推求出答案,于是就有了 与 。
会受到后面加入的节点的影响而变化,故考虑将 ,其中 表示 号节点的深度(根节点深度为 ),原因显然,只不过是换了一种统计的方式。
那么 ,还是不太好做,考虑平均贡献,也就是期望,转化为 。
那么只需要求出 ,有转移:
记 ,则 。
接下来考虑 的变化量,拆为 (每棵 个节点树都有 种加点方法变为 个节点的树),和节点 带来的新变化:其到根的路径上的每个节点的 都会加 ,同时它自己会有 的 。
考虑推一推后者的式子:
考虑 那部分的实质,得到:
于是得到最终的递推式,
~完结撒花~。
CPP#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,l,r) for(int i=(r);i>=(l);--i)
#define pr pair<int,int>
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define bg(x) (x).begin()
#define ed(x) (x).end()
#define N 1000010
#define int long long
const int mod=1e9+7;
inline int qpow(int a,int b=mod-2){
int ans=1;
while(b){
if(b&1){
ans=ans*a%mod;
}
a=a*a%mod;
b>>=1;
}
return ans;
}
int n,fac[N],iv[N],s[N],g[N],f[N];
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
fac[0]=1;
rep(i,1,n){
fac[i]=fac[i-1]*i%mod;
}
iv[n]=qpow(fac[n]);
per(i,0,n-1){
iv[i]=iv[i+1]*(i+1)%mod;
}
rep(i,0,n){
iv[i]=iv[i]*fac[i-1]%mod;
}
rep(i,1,n){
s[i]=s[i-1]*iv[i-1]%mod+1;
s[i]=(s[i-1]+s[i])%mod;
g[i]=s[i]*fac[i-1]%mod;
}
f[1]=1;
rep(i,2,n){
f[i]=(i+1)*f[i-1]%mod+g[i-1]+fac[i-1];
f[i]%=mod;
}
cout<<f[n]<<'\n';
return 0;
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...