AT2272 [ARC066B] Xor Sum 题解
题目连接:传送门
分析
这道题只看题目中给的样例是找不出规律的
所以我们可以打一下表
1, 2, 4, 5, 8, 10, 13, 14, 18
如果你还是没有看出什么规律的话,我们可以从OEIS上搜索一下
网址:传送门
把这一个数列输入到搜索框,然后就会出现下面的页面
第一个就是我们想要的数列
大家可以看一下上面的证明和递推式(都是英文)
所以我们可以得到\(f[x]=f[x/2]+f[(x-1)/2]+f[(x-2)/2]\)
证明摘自洛谷:
代码
#include<cstdio>
#include<map>
#define ll long long
using namespace std;
const int Mod=1e9+7;
map<ll,ll> dp;
ll dfs(ll x){
if(dp[x])return dp[x];
return dp[x]=(dfs(x>>1)+dfs(x-1>>1)+dfs(x-2>>1))%Mod;
}
int main(){
ll n;
scanf("%lld",&n);
dp[0]=1;
dp[1]=2;
ll res=dfs(n)%Mod;
printf("%lld\n",res);
}
//打表
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
map<ll,ll> ma;
ll a[50]={1,2,4,5,8,10,13,14,18,21,26,28,33,36,40,41,46,50,57,60,68};
ll solve(ll xx){
if(xx<=20) return a[xx];
if(ma[xx]) return ma[xx];
if(xx%2) return ma[xx]=(2*solve(xx/2)%mod+solve(xx/2-1)%mod)%mod;
else return ma[xx]=(2*solve(xx/2-1)%mod+solve(xx/2)%mod)%mod;
}
int main(){
ll n;
scanf("%lld",&n);
ll ans=solve(n);
printf("%lld\n",ans);
return 0;
}