思路:
经过分析可得:
f(2 * k) = 3 * f(k)
f(2 * k + 1) = 3 * f(k) + 1
然后:f(x) = 把x用二进制表示出来后,用三进制来计算得到的数值
如:x = 5时,二进制为101,所以f(5) = 1 * 3^2 + 0 * 3^1 + 1 * 3^0 = 10
有了这个之后我们把1~n的数,变成二进制,写成一列,比如n = 5类似这个样子:
000
001
010
011
100
101
然后我们发现其实可以dp搞定这道题,dp[i][j],其中i表示dp到第i个二进制位的时候,mod = j有多少个数,然后就是计算1~n的数在某一位二进制位上的0和1的个数,进行转移,大概这个样子。
skt的代码,不是我写的
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define MAXN 65540
int T;
LL N, K, g[64][2][MAXN], tmp[MAXN], t[64];
void work() {
scanf("%lld %lld", &N, &K);
if (N == 1) {
cout << 1 << endl;
return ;
}
if (K == 3) {
LL p1 = N / 2, p2 = N - p1;
cout << (p1 ^ p2) << endl;
return ;
}
memset(tmp, 0, sizeof(tmp));
memset(g[0], 0, sizeof(g[0]));
g[0][0][0] ++;
g[0][1][1 % K] ++;
LL three = 1LL;
int bit = 0;
t[0] = 1;
for (int i = 1; (1ll << i) <= N; i ++) {
bit = max(bit, i);
fill(g[i][0], g[i][0] + K + 1, 0);
fill(g[i][1], g[i][1] + K + 1, 0);
three *= 3LL;
three %= K;
t[i] = three;
for (int j = 0; j < K; j ++) {
g[i][1][(j + three) % K] += g[i - 1][0][j];
g[i][1][(j + three) % K] += g[i - 1][1][j];
}
for (int j = 0; j < K; j ++) {
g[i][0][j] += g[i - 1][0][j];
g[i][0][j] += g[i - 1][1][j];
}
}
LL add = 0LL;
for (int i = bit; i >= 0; i --) {
if (N & (1ll << i)) {
for (int j = 0; j < K; j ++) {
tmp[(j + add) % K] += g[i][0][j];
}
add += t[i];
}
}
tmp[add % K] ++;
tmp[0] --;
LL res = 0LL;
for (int i = 0; i < K; i ++) {
res ^= tmp[i];
}
cout << res << endl;
}
int main() {
#ifdef __SKT__
freopen("in", "r", stdin);
#endif
scanf("%d", &T);
while (T --) {
work();
}
return 0;
}