1. 程式人生 > >解題:HEOI 2013 SAO

解題:HEOI 2013 SAO

none ref 技術分享 void init spl class 當前 include

題面

不好講,直接上式子吧=。=

設$dp[i][j]$表示考慮完$i$的子樹後$i$的排名為$j$的方案數,然後轉移類似樹形背包,具體來說是(這裏假設子樹在$i$後選,其實反過來還用這個式子答案也是一樣的,因為全反了)

$ans+=dp[nde][k]*dp[g][min(j-k,siz[g])]*C_{j-1}^{k-1}*C_{siz[nde]+siz[g]-j}^{siz[nde]-k}$

其中$j$是枚舉的當前點加入這個子樹之後的size,$k$是枚舉的當前點加入這個子樹之前的size,$g$是子樹,解釋一下

前兩個是已有的

技術分享圖片
 1 #include<cstdio>
 2
#include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=1005,mod=1e9+7; 6 int fac[N],inv[N],siz[N],f[N][N]; 7 int p[N],noww[2*N],goal[2*N],val[2*N]; 8 int T,n,t1,t2,cnt; char rd[5]; 9 void Link(int f,int t,int v) 10 { 11 noww[++cnt]=p[f],p[f]=cnt; 12 goal[cnt]=t,val[cnt]=v;
13 } 14 int Qpow(int x,int k) 15 { 16 if(k==1) return x; 17 int tmp=Qpow(x,k/2); 18 return k%2?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod; 19 } 20 int C(int a,int b) 21 { 22 if(a<b) return 0; 23 return 1ll*fac[a]*inv[b]%mod*inv[a-b]%mod; 24 } 25 void Prework() 26 { 27 fac[0]=inv[0]=1
; 28 for(int i=1;i<=1000;i++) 29 fac[i]=1ll*fac[i-1]*i%mod; 30 inv[1000]=Qpow(fac[1000],mod-2); 31 for(int i=999;i;i--) 32 inv[i]=1ll*inv[i+1]*(i+1)%mod; 33 scanf("%d",&T); 34 } 35 void Init() 36 { 37 memset(p,0,sizeof p); 38 memset(f,0,sizeof f); 39 cnt=0,scanf("%d",&n); 40 for(int i=1;i<n;i++) 41 { 42 scanf("%d%s%d",&t1,rd,&t2),t1++,t2++; 43 Link(t1,t2,rd[0]==<),Link(t2,t1,rd[0]==>); 44 } 45 for(int i=1;i<=n;i++) f[i][1]=1; 46 } 47 void DFS(int nde,int fth) 48 { 49 siz[nde]=1; 50 for(int i=p[nde];i;i=noww[i]) 51 { 52 int g=goal[i]; 53 if(g!=fth) 54 { 55 DFS(g,nde); 56 if(val[i]) 57 { 58 for(int j=siz[nde]+siz[g];j;j--) 59 { 60 int tmp=0; 61 for(int k=1;k<=min(j,siz[nde]);k++) 62 if(j-k+1<=siz[g]) 63 tmp+=1ll*f[nde][k]*(f[g][siz[g]]-f[g][j-k]+mod)%mod*C(j-1,k-1)%mod*C(siz[nde]+siz[g]-j,siz[nde]-k)%mod,tmp%=mod; 64 f[nde][j]=tmp; 65 } 66 } 67 else 68 { 69 for(int j=siz[nde]+siz[g];j;j--) 70 { 71 int tmp=0; 72 for(int k=1;k<=min(j,siz[nde]);k++) 73 if(min(j-k,siz[g])>=1) 74 tmp+=1ll*f[nde][k]*f[g][min(j-k,siz[g])]%mod*C(j-1,k-1)%mod*C(siz[nde]+siz[g]-j,siz[nde]-k)%mod,tmp%=mod; 75 f[nde][j]=tmp; 76 } 77 } 78 siz[nde]+=siz[g]; 79 } 80 } 81 for(int i=1;i<=siz[nde];i++) 82 f[nde][i]=(f[nde][i]+f[nde][i-1])%mod; 83 } 84 int main() 85 { 86 Prework(); 87 while(T--) 88 Init(),DFS(1,0),printf("%d\n",f[1][n]); 89 return 0; 90 }
View Code

解題:HEOI 2013 SAO