test20181024 zi
阿新 • • 發佈:2018-10-25
bit amp open esp get pen 內容 n) http
題意
分析
這種題一般是推公式,發現必須求得的量,然後定義函數記憶化。
然後那些函數裏面又是遞歸處理,合並。
代碼
為了不爆空間,用map存記憶化內容。
#include<bits/stdc++.h> using namespace std; #define gc c=getchar() #define r(x) read(x) #define ll long long template<typename T> inline void read(T&x) { x=0; T k=1; char gc; while(!isdigit(c)) { if(c==‘-‘)k=-1; gc; } while(isdigit(c)) { x=x*10+c-‘0‘; gc; } x*=k; } const int p=1e9+7; const int N=65; struct Tree { ll a,b,c,d,l,siz,ans; } A[N]; map<pair<pair<int,ll>,ll>,ll>mp; ll dfs2(int rt,ll u,ll v) { if(!rt) return 0; pair<pair<int,int>,int> Hash=make_pair(make_pair(rt,u),v); if(mp[Hash]) return mp[Hash]; Tree &t=A[rt]; ll &ans=mp[Hash]; if(u==v) return 0; if(u<A[t.a].siz&&v<A[t.a].siz) return ans=dfs2(t.a,u,v); if(u<A[t.a].siz&&v>=A[t.a].siz) return ans=(dfs2(t.a,t.c,u)+dfs2(t.b,t.d,v-A[t.a].siz)+t.l)%p; if(u>=A[t.a].siz&&v<A[t.a].siz) return ans=(dfs2(t.a,t.c,v)+dfs2(t.b,t.d,u-A[t.a].siz)+t.l)%p; return ans=dfs2(t.b,u-A[t.a].siz,v-A[t.a].siz); } map<pair<int,ll>,ll>mpp; ll dfs1(int rt,ll x) //T_rt 以 x 為根,所以點的(子樹大小*邊權)之和 { if(!rt) return 0; Tree &t=A[rt]; pair<int,ll> Hash=make_pair(rt,x); if(mpp[Hash]) return mpp[Hash]; ll &ans=mpp[Hash]; if(x<A[t.a].siz) return ans=(dfs1(t.b,t.d)+dfs1(t.a,x)+A[t.b].siz%p*(dfs2(t.a,t.c,x)+t.l)%p)%p; else return ans=(dfs1(t.a,t.c)+dfs1(t.b,x-A[t.a].siz)+A[t.a].siz%p*(dfs2(t.b,t.d,x-A[t.a].siz)+t.l)%p)%p; } int main() { freopen("zi.in","r",stdin); freopen("zi.out","w",stdout); int m; r(m); A[0].siz=1; for(int i=1; i<=m; ++i) { Tree &x=A[i]; r(x.a),r(x.b),r(x.c),r(x.d),r(x.l); x.siz=A[x.a].siz+A[x.b].siz; x.ans=(A[x.a].ans+A[x.b].ans +(ll)(A[x.a].siz%p)*(A[x.b].siz%p)%p*x.l%p +A[x.b].siz%p*dfs1(x.a,x.c)%p +A[x.a].siz%p*dfs1(x.b,x.d)%p)%p; printf("%lld\n",x.ans); } }
test20181024 zi