题解:
可以考虑每一层结点的子树大小
必定满足下面的情况,即
a,a,a,a,a,a,b,c,c,c,c........
然后每一层依次往上更新,结果是不变的
一共有logn层,所以依次扫上去,统计结果即可
注意到k=1的时候,是一条链,需要特殊处理orz
这个打表可以发现明显的规律,也是二进制的一种容斥吧
#include <iostream> #include <cstdio> #include <cmath> using namespace std; typedef long long LL; typedef long long ll; LL n, k; LL mypow(LL a, LL b){ if( pow((double)a, b) > 1.5e18) return 1e18; LL ans = 1; for(; b; b >>= 1) { if(b&1) ans *= a; a *= a; } return ans; } int main() { int T; cin>>T; while(T--){ cin>>n>>k; if(n == 1){ cout<<1<<endl; continue; } if(k == 1){ LL t = n%4; if(t == 1) cout<<1<<endl; else if(t == 2) cout<<n+1<<endl; else if(t == 3) cout<<0<<endl; else cout<<n<<endl; continue; } LL d = 0, sum = 0; while(sum + mypow(k, d) <= n) sum += mypow(k, d), d++; if(sum == n){ d--; LL ans = 0, sz = 1; while(d != -1){ LL N = mypow(k, d); if(N&1) ans ^= sz; sz = 1+sz*k; d--; } cout<<ans<<endl; continue; } LL N = n - sum, ans = 0; LL X = N, L = 1, R = 0, Xv = 1, D = d; while(d){ LL dL = mypow(k, d); ans ^= Xv; if((X-1)&1) ans ^= L; if((dL-X)&1) ans ^= R; LL Nl = X-1; LL Nx = Nl/k*k + 1, Nfx = X-Nx; LL Ny = Nx+k-1, Nfy = Ny-X; Xv = Nfx*L + Nfy*R + Xv + 1; if((double)L*k < 1.5e18) L = 1+L*k; R = 1+R*k; X = (Nx-1)/k + 1; d--; } ans ^= Xv; cout<<ans<<endl; } }