2015ACM/ICPC 北京站 K題 數論 + 搜尋
阿新 • • 發佈:2019-02-02
題意:
給定一個數列
然後給你一個
然後問
思路:
對於
設:
則
因為
而
所以
即:
故我們可以推出
當
當
故可以考慮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;
}