【暴力】hdu6121 Build a tree

给你n,K,让你构造出一颗n个结点的完全K叉树,求所有结点子树大小的异或和。

先把n号结点到根的路径提取出来单独计算。然后这条路径把每一层分成了左右两部分,每一层的左侧和其上一层的右侧的结点的子树大小相同。

就可以容易计算每种大小的子树个数了。

当K等于1时,要单独讨论,答案为1 xor 2 xor ... xor n。这个打个表非常明显。

#include
using namespace std;
typedef long long ll;
ll n,K,pw[105];
int T;
int main(){
//	freopen("1002.in","r",stdin);
//	freopen("1002.out","w",stdout);
	scanf("%d",&T);
	for(;T;--T){
		scanf("%lld%lld",&n,&K);
		if(K==1){
			if(n%4ll==0){
				printf("%lld\n",n);
			}
			else if(n%4ll==1ll){
				printf("%lld\n",1ll);
			}
			else if(n%4ll==2ll){
				printf("%lld\n",n+1ll);
			}
			else{
				printf("%lld\n",0ll);
			}
			continue;
		}
		pw[0]=1;
		int j;
		for(j=1;pw[j-1]<=n/K;++j){
			pw[j]=pw[j-1]*K;
		}
		--j;
		int e=j;
		for(int k=1;k<=j;++k){
			if(pw[k-1]>n-pw[k]){
				e=k-1;
				break;
			}
			pw[k]+=pw[k-1];
		}
		if(n==pw[e]){
			--e;
		}
		ll i=n-1ll;
		ll now=n;
		ll nowsiz=1,sumnowsiz=1;
		ll ans=1;
		ll sheng=((n-pw[e])%K!=0 ? (n-pw[e])%K : K);
		int E=e;
		while(i!=0){
			ll fa=(i-1)/K;
			if((i-1ll-fa)%2ll==1ll){
				ans^=sumnowsiz;
			}
			ans^=(sumnowsiz+sheng);
			now=pw[e];
			--e;
			i=fa;
			nowsiz*=K;
			sumnowsiz+=nowsiz;
			sheng=((n-pw[E])%(nowsiz*K)!=0 ? (n-pw[E])%(nowsiz*K) : (nowsiz*K));
		}
		printf("%lld\n",ans);
	}
	return 0;
}

转载于:https://www.cnblogs.com/autsky-jadek/p/7376605.html

你可能感兴趣的:(【暴力】hdu6121 Build a tree)