题解 洛谷 P5689 【[CSP-SJX2019]多叉堆】
一整棵树的答案很显然是一样的,所以我们可以考虑并查集维护。
我们可以用 表示以 为根的子树大小。注意这里,如果 已经是一棵树上的节点,那么就不用维护了。这个显然可以维护:在合并的时候相加即可。
再用 表示以 为根的答案。考虑当把以 为根的树接在以 为根的树下,则 。这个很好理解,就是因为 这个数只能放在根上,其他 个数任选出 个数摆在以 为根的树上,其它数摆在以 为根的树上,两个方案相乘即可。
至于组合数怎么求,预处理一下阶乘和阶乘的逆元就行了。
结合代码理解下(不要在意奇怪的变量名比如 是阶乘的意思)。
#include<bits/stdc++.h>
using namespace std;
int n,m;
int fa[300501];
int size[300001];
long long ans[300001];
const long long mod=1e9+7;
long long jc[300001],njc[300001];
inline long long read()
{
char C;
long long F=1,ANS=0;
while (C<'0'||C>'9')
{
if (C=='-') F=-1;
C=getchar();
}
while (C>='0'&&C<='9')
{
ANS=ANS*10+C-'0';
C=getchar();
}
return F*ANS;
}
long long ksm(long long x,int y)
{
if (y==0) return 1;
long long res=ksm(x,y/2);
res=(res*res)%mod;
if (y%2==0) return res;
return (res*x)%mod;
}
inline long long C(int x,int y)
{
return ((jc[x]*njc[y])%mod)*njc[x-y]%mod;
}
inline int find(int x)
{
if (x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
int main()
{
n=read(),m=read();
for (int i=0;i<n;i++) fa[i]=i,size[i]=1,ans[i]=1;
jc[0]=1;
for (int i=1;i<=n;i++) jc[i]=(jc[i-1]*i)%mod;
njc[n]=ksm(jc[n],mod-2);
for (int i=n-1;i>=0;i--) njc[i]=(njc[i+1]*(i+1))%mod;
long long lastans=0;
for (int i=1;i<=m;i++)
{
int x,y,t;
t=read(),x=read();
x=(x+lastans)%n;
if (t==1)
{
y=read();
y=(y+lastans)%n;
int x1=find(x),y1=find(y);
ans[y1]=((ans[y1]*ans[x1])%mod*C(size[x1]+size[y1]-1,size[x1]))%mod;
size[y1]+=size[x1];
fa[x1]=y1;
}
else
{
lastans=ans[find(x)];
printf("%lld\n",lastans);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构