#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
考慮一次詢問,若知道 Sl−1,就可以知道 Sr,S 爲異或前綴和,那麼我們將 l−1 與 r 連邊,最終就是一棵最小生成樹,在 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
枚舉 B 的根,記 dpi,j 爲到 i 拼出 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;}