题目链接:点击打开链接
题目大意:给定一棵有n个结点的k叉树,求所有子树的大小的异或和~~~
多校补题日记~~~
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long llt;
llt SIZE[100];
llt L[100];
//完全k叉树
llt complete(llt n,int depth,int k)
{
if((k&1)==0) return n;
else
{
llt ans=0;
for(int i=1;i<=depth;i++)
ans^=SIZE[i];
return ans;
}
}
//不平衡的k叉树
llt dfs(llt n,int depth,int k)
{
llt ret=n;
llt rem=n-SIZE[depth];
if(rem%L[depth]==0)
{
llt comp=rem/L[depth];
if(comp&1) ret^=complete(SIZE[depth],depth,k);
if((k-comp)&1) ret^=complete(SIZE[depth-1],depth-1,k);
return ret;
}
else
{
llt comp=rem/L[depth];
llt cut=rem%L[depth];
if(comp&1) ret^=complete(SIZE[depth],depth,k);
if((k-comp-1)&1) ret^=complete(SIZE[depth-1],depth-1,k);
return ret^dfs(SIZE[depth-1]+cut,depth-1,k);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
llt n,k;
scanf("%lld%lld",&n,&k);
if(k==1)
{
if(n%4==1) printf("%d\n",1);
else if(n%4==2) printf("%d\n",n+1);
else if(n%4==3) printf("%d\n",0);
else printf("%d\n",n);
continue;
}
int depth=1;
llt sum=1,left=k;
L[1]=1;
while(sum+left<=n)
{
SIZE[depth]=sum;
L[++depth]=left;
sum+=left;
left*=k;
}
SIZE[depth]=sum;
if(sum==n) printf("%lld\n",complete(n,depth,k));
else printf("%lld\n",dfs(n,depth,k));
}
return 0;
}