其他题目题解:
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 long
LL 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;
}