HDU 5593 ZYB's Tree (樹形DP)
阿新 • • 發佈:2018-12-16
#pragma comment(linker,"/STACK:1024000000,1024000000") #include<bits/stdc++.h> using namespace std; #define debug puts("YES"); #define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++) #define ll long long #define lrt int l,int r,int rt #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define root l,r,rt const int maxn =5e5+5; const int mod=1e9+7; const int ub=1e6; ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;} ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} /* 題目大意:給定一個 生成樹的方法A和B, 然後統計對於每個點, 距離不超過k的節點數量, 對於每個點這樣的權重值異或起來就是最後的答案。 典型的樹形DP, 兩邊DFS即可,第一遍只記錄向下的關於距離k的節點個數, 第二遍利用所求從上往下更新狀態即可,由於遞推關係, 第二遍更新DP陣列的順序要注意下。 */ ///鏈式前向星 struct node{int u,nxt;}e[maxn<<1]; int head[maxn],tot=0; void init(){memset(head,-1,sizeof(head));tot=0;} void add(int x,int y){e[tot]=node{y,head[x]};head[x]=tot++;} ///資料域 ll n,k,a,b; ll dp[maxn][11]; void dfs1(int u,int pre) { dp[u][0]=1; for(int i=head[u];~i;i=e[i].nxt) { int v=e[i].u; if(v==pre) continue; dfs1(v,u); for(int j=1;j<=10;j++) dp[u][j]+=dp[v][j-1]; } } void dfs2(int u,int pre) { if(pre!=-1) for(int j=10;j>=1;j--)///注意DP的時間序問題 { dp[u][j]+=dp[pre][j-1]; if(j>=2) dp[u][j]-=dp[u][j-2]; } for(int i=head[u];~i;i=e[i].nxt) { int v=e[i].u; if(v==pre) continue; dfs2(v,u); } } int main() { int t;scanf("%d",&t); while(t--) { scanf("%lld%lld%lld%lld",&n,&k,&a,&b); memset(dp,0,sizeof(dp));init();///初始化 for(int i=2;i<=n;i++) { ll tmp=((ll)a*i+b)%(i-1)+1;///注意可能會爆資料範圍 add(i,tmp),add(tmp,i); } dfs1(1,-1);dfs2(1,-1); for(int i=1;i<=n;i++) for(int j=1;j<=10;j++) dp[i][j]+=dp[i][j-1]; ll ans=0;for(int i=1;i<=n;i++) ans^=dp[i][k]; printf("%d\n",ans); } return 0; }