题意:
给定一个数列
F
F
F,满足:
F
[
1
]
=
1
F[1] = 1
F[1]=1
3
F
[
n
]
∗
F
[
2
n
+
1
]
=
F
[
2
n
]
∗
(
1
+
3
F
[
n
]
)
3F[n]*F[2n+1] = F[2n]*(1 + 3F[n])
3F[n]∗F[2n+1]=F[2n]∗(1+3F[n])
F
[
2
n
]
<
6
F
[
n
]
F[2n] < 6F[n]
F[2n]<6F[n]
然后给你一个
n
,
k
n,k
n,k,定义
g
[
i
]
g[i]
g[i]为
F
[
1
]
−
F
[
n
]
F[1]-F[n]
F[1]−F[n]对
k
k
k取余后等于
i
i
i的个数。
然后问
g
[
0
]
−
g
[
k
−
1
]
g[0]-g[k-1]
g[0]−g[k−1]的异或和。
思路:
对于
F
F
F,考虑第二个条件,化简可得:
F
[
2
n
+
1
]
F
[
2
n
]
=
1
+
3
F
[
n
]
3
F
[
n
]
\frac{F[2n+1]}{F[2n]} = \frac{1+3F[n]}{3F[n]}
F[2n]F[2n+1]=3F[n]1+3F[n]
设:
F
[
2
n
]
=
k
∗
3
F
[
n
]
F[2n] = k*3F[n]
F[2n]=k∗3F[n]
则
F
[
2
n
+
1
]
=
k
∗
(
1
+
3
F
[
n
]
)
F[2n+1] = k*(1+3F[n])
F[2n+1]=k∗(1+3F[n])
因为
F
[
2
n
]
<
6
F
[
n
]
F[2n] < 6F[n]
F[2n]<6F[n]
而
k
>
=
1
k >= 1
k>=1
所以
k
=
1
k = 1
k=1
即:
F
[
2
n
]
=
3
F
[
n
]
F[2n] = 3F[n]
F[2n]=3F[n]
F
[
2
n
+
1
]
=
1
+
3
F
[
n
]
F[2n+1] = 1 + 3F[n]
F[2n+1]=1+3F[n]
故我们可以推出
当
n
n
n为奇数,
F
[
n
]
=
3
∗
F
[
n
/
2
]
F[n] = 3*F[n/2]
F[n]=3∗F[n/2]
当
n
n
n为偶数,
F
[
n
]
=
3
∗
F
[
n
/
2
]
+
1
F[n] = 3*F[n/2] + 1
F[n]=3∗F[n/2]+1
故可以考虑DFS,每次可以将问题规模减小一半。
以上。
代码:
#include<cstdio>
#include<cmath>
#include<set>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int A = 1e5 + 10;
ll g[A],tg[A],k;
ll n;
ll calc(ll n){
if(n == 1) return 1;
if(n&1) return (3*calc(n/2)+1)%k;
return 3*calc(n/2)%k;
}
void dfs(ll n){
if(n == 1){
g[1]++;
return;
}
if(n&1){
dfs(n-1);
g[calc(n)]++;
}
else{
dfs(n/2);
for(int i=0 ;i<k ;i++) tg[i] = 0;
for(int i=0 ;i<k ;i++){
tg[(i*3)%k] += g[i];
tg[(i*3+1)%k] += g[i];
}
for(int i=0 ;i<k ;i++) g[i] = tg[i];
g[1]++;
g[calc(n+1)]--;
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%lld%lld",&n,&k);
memset(g,0,sizeof(g));
dfs(n);
ll ans = 0;
for(int i=0 ;i<k ;i++){
ans ^= g[i];
}
printf("%lld\n",ans);
}
return 0;
}