2017 Multi-University Training Contest

来源:互联网 发布:mysql数据库常用语句 编辑:程序博客网 时间:2024/05/17 03:04

其他题目题解:

2017 Multi-University Training Contest - Team 7:1005. Euler theorem

2017 Multi-University Training Contest - Team 7:1011. Kolakoski

2017 Multi-University Training Contest - Team 7:1008. Hard challenge

2017 Multi-University Training Contest - Team 7:1003. Color the chessboard

2017 Multi-University Training Contest - Team 7:1010. Just do it




题意:有一棵n个点的有根数,根编号为0,i号节点的父亲是(i-1)/k号节点

求出所有子树大小的异或和


性质:对于一颗满k叉树而言,如果k是偶数,那么它的异或和就是树的大小

如果k是奇数,那么它的异或和就是任意一棵子树大小的异或和再异或树的大小

而这题的树也有几个性质:

①假设n足够大,那么根有k个儿子(废话)

这k棵子树最多只有一棵不是满二叉树

那么假设k不等于1,二叉树的深度不会超过63

所以只要找到是哪棵子树不是满二叉树,以那棵子树作为整棵树求它的异或和很显然子树也具有一样的性质这样就可以递归求解,求出来之后直接异或其它所有满二叉树的大小就是答案,注意别忘记异或上n

还有k=1要特判

#include<stdio.h>#define LL long longLL tre[125] = {1};int main(void){LL T, n, k, ans, now, last, x, l, r, full;scanf("%lld", &T);while(T--){scanf("%lld%lld", &n, &k);if(k==1){switch(n%4){case 1:  printf("1\n");  break;case 2:  printf("%lld\n", n+1);  break;case 3:  printf("0\n");  break;case 0:  printf("%lld\n", n);  break;}}else{ans = n;while(1){if(n-1<=k){if(n%2==0)ans ^= 1;printf("%lld\n", ans);break;}now = x = full = 1;while(0<=now+x*k && now+x*k<n){x = x*k;now += x;full ^= now;}last = n-now;l = (last-1)/x;r = k-l-1;if(k%2==0){if(l%2==1)  ans ^= now;if(r%2==1)  ans ^= (now-x);}else{if(l%2==1)  ans ^= full;if(r%2==1)  ans ^= full^now;}n -= l*now+r*(now-x)+1;ans ^= n;}}}return 0;}