容易发现,答案即为
n
!
∏
s
i
z
e
i
\frac{n!}{\prod size_i}
∏sizein!,考虑从根开始往下走,一定存在一个子树是满儿叉树,将其系数预处理出来就可以
O
(
log
n
)
O(\log n)
O(logn) 询问,阶乘需要打一个表
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
cs int Mod =1e9+7;intadd(int a,int b){return a + b >= Mod ? a + b - Mod : a + b;}intdec(int a,int b){return a - b <0 ? a - b + Mod : a - b;}intmul(int a,int b){return1ll * a * b % Mod;}
void Add(int&a,int b){ a =add(a,b);}
void Dec(int&a,int b){ a =dec(a,b);}
void Mul(int&a,int b){ a =mul(a,b);}intksm(int a,int b){int as=1;for(;b;b>>=1,Mul(a,a))if(b&1)Mul(as,a);return as;}int fc[1050]={};int ans[40]={};
cs int S =1e6;intfac(int n){int t = n / S, ans = fc[t];for(int i = t * S +1; i <= n; i++)Mul(ans,i);return ans;}int n;intmain(){freopen("heap.in","r",stdin);freopen("heap.out","w",stdout);scanf("%d",&n);int d =0, x = n;while(x)++d, x>>=1;--d;int Ans =fac(n);if(!(n &(n+1)))returnmul(Ans,ans[d]),0;
x = n;while(x >1){Mul(Ans,ksm(x,Mod-2));int t = x -(1<< d);if(t >=(1<<(d-1)))Mul(Ans, d?ans[d-1]:1), x -=(1<<d);elseMul(Ans, d>1?ans[d-2]:1), x -=(1<<(d-1));--d;} cout << Ans;return0;}
B
B
B
考虑一次询问,若知道
S
l
−
1
S_{l-1}
Sl−1,就可以知道
S
r
S_r
Sr,
S
S
S 为异或前缀和,那么我们将
l
−
1
l-1
l−1 与
r
r
r 连边,最终就是一棵最小生成树,在
t
r
i
e
trie
trie 树上贪心,考虑高位的两个子树一定只有一对连边,启发式合并在另一个里面查就可以了
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
namespace IO{
cs int Rlen=1<<22|1;
inline char gc(){
static char buf[Rlen],*p1,*p2;(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));return p1==p2?EOF:*p1++;}intgi(){int x=0; char c=gc();while(!isdigit(c))c=gc();while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48),c=gc();return x;}} using namespace IO;
typedef long long ll;
cs int N =1e5+50;
cs int INF =2147483647;int n, a[N], rt[N];
cs int M = N <<5;int ch[M][2], nd, vl[M];bool ed[M];
void ins(int x){int u=0;for(int i=30,c;~i;i--){
c=x>>i&1;if(!ch[u][c])
ch[u][c]=++nd; u=ch[u][c];} vl[u]=x; ed[u]=true;}int sz[M], ban, now; ll Ans;intqry(int x){int u=0;for(int i=30,c;~i;i--){
c=x>>i&1;if(!ch[u][c])c^=1;if(ban==u)c^=1;u=ch[u][c];}return vl[u];}
void _cope(int u){if(ch[u][0])_cope(ch[u][0]);if(ch[u][1])_cope(ch[u][1]);if(ed[u])now=min(now,vl[u]^qry(vl[u]));}
void cope(int u){if(ch[u][0])cope(ch[u][0]);if(ch[u][1])cope(ch[u][1]);
sz[u]=sz[ch[u][0]]+sz[ch[u][1]]+1;if(ch[u][0]&&ch[u][1]){
ban = u; now = INF;if(sz[ch[u][0]]<sz[ch[u][1]])_cope(ch[u][0]);else_cope(ch[u][1]); Ans+=(ll)now;}}intmain(){freopen("secret.in","r",stdin);freopen("secret.out","w",stdout);
n=gi();for(int i=1; i<=n; i++)
a[i]=gi()^a[i-1];for(int i=0; i<=n; i++)ins(a[i]);cope(0); cout<<Ans;return0;}
C
C
C
枚举
B
B
B 的根,记
d
p
i
,
j
dp_{i,j}
dpi,j 为到
i
i
i 拼出
j
j
j 的子树的方案数,子树同构要除一个阶乘的系数
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
namespace IO{
cs int Rlen=1<<22|1;
inline char gc(){
static char buf[Rlen],*p1,*p2;(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));return p1==p2?EOF:*p1++;}intgi(){int x=0; char c=gc();while(!isdigit(c))c=gc();while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48),c=gc();return x;}} using namespace IO;
typedef long long ll;
typedef unsigned long long ull;
cs int Mod =1e9+7;intadd(int a,int b){return a + b >= Mod ? a + b - Mod : a + b;}intdec(int a,int b){return a - b <0 ? a - b + Mod : a - b;}intmul(int a,int b){return1ll * a * b % Mod;}
void Add(int&a,int b){ a =add(a,b);}
void Dec(int&a,int b){ a =dec(a,b);}
void Mul(int&a,int b){ a =mul(a,b);}intksm(int a,int b){int as=1;for(;b;b>>=1,Mul(a,a))if(b&1)Mul(as,a);return as;}
cs int N =1<<12|5, M =20;int n, m; vector<int> A[N], B[M], C[M];
ull h[M], pw[M<<1];int sz[M];boolcmp(int a,int b){return h[a]< h[b];}int dp[N][M], coe[M], ifc[M];
void pre_dfs(int u,int f){
h[u]=0; sz[u]=1; C[u].clear();for(int e=0,v;e<(int)B[u].size();e++)if((v=B[u][e])!=f)pre_dfs(v,u),C[u].pb(v);sort(C[u].begin(),C[u].end(),cmp);for(int e=0,v; e<(int)C[u].size(); e++){
v=C[u][e]; sz[u]+= sz[v];
h[u]= h[u]* pw[sz[v]<<1]+ h[v];} h[u]= h[u]* pw[sz[u]+sz[u]-1]+1;
coe[u]=1;for(int e=0,v,t=0; e<(int)C[u].size(); e=t){
v=C[u][e];while(t<(int)C[u].size()&&h[v]==h[C[u][t]])++t;Mul(coe[u],ifc[t-e]);}}
void dfs(int u,int fa){for(int e=0,v;e<(int)A[u].size();e++)if((v=A[u][e])!=fa)dfs(v,u);for(int i=1; i<=m; i++){
static int ic[M];int ct =0;for(int j=1; j<=m; j++) ic[j]=-1;for(int e=0;e<(int)C[i].size();e++)
ic[C[i][e]]= ct++;if(!ct){ dp[u][i]=1;continue;}
static int f[2][N];int S =1<<ct, now =0, nxt =1;for(int j=0; j<S; j++) f[0][j]=0; f[0][0]=1;for(int e=0,v;e<(int)A[u].size();e++)if((v=A[u][e])!=fa){memset(f[nxt],0,sizeof(f[nxt]));for(int i=1,t; i<=m; i++)if(~(t=ic[i])){for(int j=1<<t;j<S;j=(j+1)|(1<<t))Add(f[nxt][j],mul(f[now][j^(1<<t)],dp[v][i]));}swap(now, nxt);for(int o=0; o<S; o++)Add(f[now][o],f[nxt][o]);} dp[u][i]=mul(coe[i],f[now][S-1]);}}intmain(){freopen("tree.in","r",stdin);freopen("tree.out","w",stdout);
n=gi();for(int i=1,u,v;i<n;i++)
u=gi(),v=gi(),A[u].pb(v),A[v].pb(u);
m=gi();for(int i=1,u,v;i<m;i++)
u=gi(),v=gi(),B[u].pb(v),B[v].pb(u);
pw[0]=1; ifc[0]=1;for(int i=1; i<=m+m; i++)pw[i]=pw[i-1]*223;for(int i=1; i<=m; i++)ifc[i]=mul(ifc[i-1],ksm(i,Mod-2));int ans=0;map<ull,int> mp;for(int r=1;r<=m;r++){pre_dfs(r,0);if(mp.count(h[r]))continue;
mp[h[r]]=true;memset(dp,0,sizeof(dp));dfs(1,0);for(int i=1; i<=n; i++)Add(ans, dp[i][r]);} cout << ans;}