题解 数叶子
考虑写个贡献形式:
枚举是哪个点是叶子,发现不可避免的需要枚举最终选定的区间
然后变形
不同的 肯定只有根号种,然后后面那个式子可以拉格朗日插值,注意因为是下降幂所以好多点值都是 0
然后题解给出了这样一个组合恒等式来优化后面的式子:
发现实际上是枚举一个区间,在区间内选一个球,在区间外选 个球
将枚举区间的过程扔到组合数里
那么留出 个特殊位置给端点
在 个位置中选出 个,然后区间就是三个相邻的球
枚举这个区间在哪里就可以了
复杂度
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define fir first
#define sec second
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m;
pair<int, int> e[N];
const ll mod=1004535809;
namespace force{
ll ans;
bool vis[N];
int id[N], rk[N], deg[N];
void dfs(int u) {
if (u>=n) {
for (int l=1; l<=m; ++l) {
int cnt=0;
for (int i=1; i<=n; ++i) deg[i]=0;
for (int r=l; r<=m; ++r) {
if (vis[r]) {
if (deg[e[rk[r]].fir]==0) ++cnt;
if (deg[e[rk[r]].fir]==1) --cnt;
++deg[e[rk[r]].fir];
if (deg[e[rk[r]].sec]==0) ++cnt;
if (deg[e[rk[r]].sec]==1) --cnt;
++deg[e[rk[r]].sec];
}
ans=(ans+cnt)%mod;
}
}
return ;
}
for (int i=1; i<=m; ++i) if (!vis[i]) {
rk[id[u]=i]=u;
vis[i]=1;
dfs(u+1);
vis[i]=0;
}
}
void solve() {
dfs(1);
printf("%lld\n", ans);
}
}
namespace task1{
int deg[N];
ll fac[N], inv[N], ans;
inline ll C(int n, int k) {return fac[n]*inv[k]%mod*inv[n-k]%mod;}
void solve() {
fac[0]=fac[1]=1; inv[0]=inv[1]=1;
for (int i=2; i<N; ++i) fac[i]=fac[i-1]*i%mod;
for (int i=2; i<N; ++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for (int i=2; i<N; ++i) inv[i]=inv[i-1]*inv[i]%mod;
for (int i=1; i<n; ++i) ++deg[e[i].fir], ++deg[e[i].sec];
for (int u=1; u<=n; ++u) {
ll tem=0;
for (int i=1; i<=m; ++i) if (m-i+1>=deg[u]) tem=(tem+i*fac[m-i+1]%mod*inv[m-i+1-deg[u]])%mod;
if (m>=deg[u]) tem=C(m+2, deg[u]+2)*fac[deg[u]]%mod;
if (m-deg[u]>=n-deg[u]-1) ans=(ans+tem*deg[u]%mod*fac[m-deg[u]]%mod*inv[m-deg[u]-(n-deg[u]-1)])%mod;
}
printf("%lld\n", ans);
}
}
namespace task{
int deg[N];
map<int, ll> mp;
ll fac[N], inv[N], ans;
inline ll C(int n, int k) {return fac[n]*inv[k]%mod*inv[n-k]%mod;}
ll calc(int d) {
if (mp.find(d)!=mp.end()) return mp[d];
if (m<d || m-d<n-d-1) return 0;
ll tem=fac[d]*inv[d+2]%mod*d%mod;
for (int i=m+2; i>m-d; --i) tem=tem*i%mod;
for (int i=m-d; i>m-n+1; --i) tem=tem*i%mod;
return mp[d]=tem;
}
void solve() {
fac[0]=fac[1]=1; inv[0]=inv[1]=1;
for (int i=2; i<N; ++i) fac[i]=fac[i-1]*i%mod;
for (int i=2; i<N; ++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for (int i=2; i<N; ++i) inv[i]=inv[i-1]*inv[i]%mod;
for (int i=1; i<n; ++i) ++deg[e[i].fir], ++deg[e[i].sec];
for (int u=1; u<=n; ++u) ans=(ans+calc(deg[u]))%mod;
printf("%lld\n", ans);
}
}
signed main()
{
freopen("leaf.in", "r", stdin);
freopen("leaf.out", "w", stdout);
n=read(); m=read();
if (m<n-1) {puts("0"); return 0;}
for (int i=1; i<n; ++i) e[i].fir=read(), e[i].sec=read();
// force::solve();
task::solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】