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;
}
posted @ 2020-05-10 18:10  liuchanglc  阅读(196)  评论(0编辑  收藏  举报