1. 程式人生 > >bzoj2152: 聰聰可可

bzoj2152: 聰聰可可

pre include ace node namespace class print lib 個數

這題一眼題就是樹形DP了,前兩天看完,結果因為高燒+流感寫不動,今天切了。

mod數極小,那麽f[i][j]表示以i為根節點的子樹中,長度%3==j的鏈的個數。

答案就是這一個子節點乘以前面的子節點的對應值,用根累計。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

struct node
{
    
int x,y,d,next; }a[41000];int len,last[21000]; void ins(int x,int y,int d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next=last[x];last[x]=len; } int A,B,f[21000][3]; void dfs(int x,int fa) { //printf("%d\n",x); f[x][0]++; for(int k=last[x];k;k=a[k].next) {
int y=a[k].y; if(y!=fa) { int d=a[k].d; dfs(y,x); A+=f[x][0]*f[y][(3-d)%3];//(這一位+d)%3==0 A+=f[x][1]*f[y][(5-d)%3]; A+=f[x][2]*f[y][(4-d)%3]; f[x][(0+d)%3]+=f[y][0]; f[x][(1+d)%3]+=f[y][1
]; f[x][(2+d)%3]+=f[y][2]; } } } int gcd(int A,int B) { if(A==0)return B; return gcd(B%A,A); } int main() { int n,x,y,w; scanf("%d",&n); len=0;memset(last,0,sizeof(last)); for(int i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&w);w%=3; ins(x,y,w);ins(y,x,w); } A=0,B=n*n; dfs(1,0);A=A*2+n; //printf("%d\n",A); int G=gcd(A,B); printf("%d/%d\n",A/G,B/G); return 0; }

bzoj2152: 聰聰可可