这场比赛是我和杰哥两个人搞的,搞了三个小时才做两个题,几何题感觉有点思路,但最近做的不多,就懒得搞,最后想了想,反正队友搞不出其他题,自己艹出一个做的比较少的题娱乐一下吧,瞄了瞄做的比较少的题,1005,求合法点对的数量,这种题一眼题啊,分治 + 统计,XWLJ了,稍微推了下calc的过程,中间统计的时候一开始想用map,然后杰哥说可能爆吧,然后由于是比赛的后半期,也就懒得想,开了个哈希表就开始写了,巴拉巴拉敲了40分钟,在比赛结束的时候交了一发,显然无果。
但随后。。。。
发现可以用一个long long保存一个节点的30个信息,这样就避免了哈希表每次的初始化(这里坨坨要超时啊),直接用map也会很快,如果比赛的时候敲得就是map,早就AC了、、、、、好水啊,题水,人更水。。。。
还是贴个代码吧,很多注释都没去,懒得去了,我还是去做做点分治+FFT吧。。sad。。。。
/* ********************************************** Author : wuyiqi Created Time: 2013-8-13 11:34:59 File Name : Cube number on a tree.cpp *********************************************** */ #include<cstdio> #include<cstring> #include<vector> #include<map> #include<algorithm> using namespace std; typedef __int64 lld; const int maxn = 50010; lld val[maxn]; int in[maxn][33]; int pri[33]; int K; int n; int head[maxn]; int nxt[maxn*2]; int pnt[maxn*2]; int E ; void add(int a,int b){ pnt[E] = b; nxt[E] = head[a]; head[a] = E++; } const int H = 100007; struct Hash_table{ int head[H]; int nxt[maxn*2]; int cnt[maxn*2]; int biao[maxn*2][33]; int E; void init() { E = 0; memset(head,-1,sizeof(head)); } int find(lld num,int x[],bool flag) { int h = num % H; for(int i = head[h]; i != -1; i = nxt[i]) { bool f = true; for(int j = 0; j < K; j++) { if(biao[i][j] != x[j]) { f = false; break; } } if(f){ int ans = cnt[i]; if(flag) cnt[i] ++; return ans; } } if(flag) { cnt[E] = 1; for(int i = 0; i < K; i++) biao[E][i] = x[i]; nxt[E] = head[h]; head[h] = E++; } return 0; } }ta; struct fenzhi { bool Del[maxn]; int size[maxn]; int opt[maxn]; int tnode[maxn] , tns; int all[maxn][33],as; int ID[maxn]; void Dfs(int u,int f) { tnode[tns++] = u; size[u] = 1; opt[u] = 0; for(int i = head[u]; i != -1; i = nxt[i]) { int v = pnt[i]; if(!Del[v] && v != f) { Dfs(v,u); size[u] += size[v]; opt[u] = max(opt[u],size[v]); } } } int Get_Root(int u){ tns = 0; Dfs(u,-1); int mi = maxn , ans = -1; for(int i = 0; i < tns; i++) { opt[tnode[i]] = max(opt[tnode[i]],size[u]-size[tnode[i]]); if(opt[tnode[i]] < mi) { mi = opt[tnode[i]]; ans = tnode[i]; } } return ans; } void Get_Dis(int u,int fa){ // printf("u=%d\n",u); int fid ; if(fa != -1) { fid = ID[fa]; for(int i = 0; i < K; i++) { all[as][i] = all[fid][i] + in[u][i]; // all[as][i] %= 3; if(all[as][i] >= 3) all[as][i] -= 3; } } else { for(int i = 0; i < K; i++) { all[as][i] = in[u][i] ; } } ID[u] = as; as++; for(int i = head[u]; i != -1; i = nxt[i]) { int v = pnt[i]; if(!Del[v] && v != fa) { Get_Dis(v,u); } } } void Solve(int u) { //printf("u=%d\n",u); u = Get_Root(u); // printf("u=%d\n",u); Ans += Calc(u,u,false); // printf("Ans=%d\n",Ans); // puts("ddd"); Del[u] = true; for(int i = head[u]; i != -1; i = nxt[i]) { int v = pnt[i]; if(!Del[v]) { int tmp = Ans; // printf("v=%d\n",v); Ans -= Calc(v,u,true); // printf("tmp=%d Ans=%d\n",tmp,Ans); } } // printf("u=%d aaaa Ans=%d\n",u,Ans); for(int i = head[u]; i != -1; i = nxt[i]) { int v = pnt[i]; if(!Del[v]) { Solve(v); } } } lld Calc(int u,int root,bool yes){ as = 0; Get_Dis(u,-1); /* for(int i = 0; i < as;i++) { for(int j = 0; j < K; j++) { // printf("all[%d][%d]=%d\n",i,j,all[i][j]); } }*/ if(yes) { // printf("u=%d root=%d\n",u,root); for(int i = 0; i < as; i++) { for(int j = 0; j < K; j++) { all[i][j] += in[root][j]; if(all[i][j] >= 3) all[i][j] -= 3; } } /* for(int i = 0; i < as; i++) { for(int j = 0; j < K; j++) { printf("all[%d][%d]=%d\n",i,j,all[i][j]); } }*/ } // printf("as=%d\n",as); lld ans = 0; // ta.init(); map<lld,int> tt; int start = (u == root) ? 1 : 0; for(int i = start; i < as; i++) { int x[33]; lld sum = 0 , g = 0; bool f = true; for(int j = 0; j < K; j++) { if(all[i][j] == 0) x[j] = 0; if(all[i][j] == 1) x[j] = 2; if(all[i][j] == 2) x[j] = 1; g<<=2; g |= x[j]; int tmp = all[i][j] - in[root][j]; if(tmp < 0) tmp += 3 ; sum<<=2; sum |= tmp; // sum = sum * 10 + tmp; if(all[i][j] != 0) f = false; } // puts("x:::"); // for(int j = 0; j < K; j++) printf("%d ",x[j]);puts(""); // puts("y:::"); // for(int j = 0; j < K; j++) printf("%d ",y[j]);puts(""); if(f && !yes) { ans++; // puts("fffff"); // puts("ddd"); }//printf("g=%d sum=%d\n",g,sum); ans += tt[g]; // printf("ans=%d\n",ans); tt[sum]++; } return ans; } lld gao() { Ans = 0; fill(Del,Del+n+1,false); Solve(1); return Ans; } lld Ans; }nice; int extr ; void split(int node,lld num) { if(num == 0) return ; bool f = true; for(int i = 0; i < K; i++) { in[node][i] = 0; if(num % pri[i] == 0) { while(num % pri[i] ==0) { num /= pri[i]; in[node][i]++; } } in[node][i] %= 3; if(in[node][i] != 0) f =false; } if(f) extr ++; // for(int i = 0; i < K; i++) printf("in[%d][%d]=%d\n",node,i,in[node][i]); } int get_val() { int ret(0); char c; while((c=getchar())==' '||c=='\n'||c=='\r'); ret=c-'0'; while((c=getchar())!=' '&&c!='\n'&&c!='\r') ret=ret*10+c-'0'; return ret; } int main() { while(scanf("%d",&n)!=EOF) { E = 0; extr = 0; fill(head,head+n+1,-1); scanf("%d",&K); for(int i = 0; i < K; i++) { // scanf("%d",&pri[i]); pri[i] = get_val(); } lld num; for(int i = 1; i <= n; i++) { scanf("%I64d",&num); split(i,num); } E = 0; for(int i = 1,a,b; i < n; i++){ a = get_val(); b = get_val(); // scanf("%d%d",&a,&b); add(a,b); add(b,a); } printf("%I64d\n",nice.gao()+extr); } return 0; } /* 4 2 2 5 100 10 100 10 1 2 2 3 3 4 7 1 2 2 2 2 2 2 2 2 1 2 1 3 2 4 2 5 3 6 3 7 5 3 2 3 5 2500 200 9 270000 27 4 2 3 5 2 5 4 1 4 7 1 6 3 2 3 5 6 1 30 150 150 12 1 2 2 4 1 3 3 5 3 6 */