BZOJ3329 Xorequ(数位dp+矩阵快速幂)

根据题意x^2x=3x

异或和普通加法的关系其实就是异或是不进位加法,我们把3x看作x+2x

这样其实求的就是异或中x和2x每一位异或都是0的答案,也就是x中没有相邻1,因为2x就是x左移而来

对于第二问,一看数据范围就知道是个数学规律题,因为普通做法不可做,观察可得,这是斐波那契数列的n+2项,因此使用矩阵快速幂

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+10;
const int mod=1e9+7;
int s[N];
ll n;
int cnt=0;
ll f[70][2][2];
struct node{
    ll a[3][3];
    void init(){
        memset(a,0,sizeof a);
    }
}S,T;
node operator *(node a,node b){
    int i,j,k;
    node tmp;
    tmp.init();
    for(i=1;i<=2;i++){
        for(j=1;j<=2;j++){
            for(k=1;k<=2;k++){
                tmp.a[i][j]=(tmp.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
            }
        }
    }
    return tmp;
}
node qpow(node a,ll k){
    node c;
    c.init();
    c.a[1][1]=c.a[2][2]=1;
    while(k){
        if(k&1){
            c=c*a;
        }
        a=a*a;
        k>>=1;
    }
    return c;
}
ll get(ll n){
    S.init();
    T.init();
    S.a[1][1]=1,S.a[2][1]=1;
    T.a[1][1]=T.a[1][2]=T.a[2][1]=1;
    T=qpow(T,n);
    S=S*T;
    return S.a[1][1];
}
ll dfs(int u,int sign,int last){
    if(u==0)
        return 1;
    auto &x=f[u][sign][last];
    if(x!=-1)
        return x;
    int up=1;
    if(sign){
        up=s[u];
    }
    int i;
    ll res=0;
    for(i=0;i<=up;i++){
        if(i){
            if(last==0)
            res+=dfs(u-1,sign&&(i==up),1);
        }
        else{
            res+=dfs(u-1,sign&&(i==up),0);
        }
    }
    return x=res;
}
ll solve(ll x){
    memset(f,-1,sizeof f);
    cnt=0;
    while(x){
        s[++cnt]=(x&1);
        x>>=1;
    }
    return dfs(cnt,1,0)-1;
}
int main(){
    ios::sync_with_stdio(false);
    int i;
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        cout<<solve(n)<<endl;
        cout<<get(n+1)<<endl;
    }
}
View Code

 

posted @ 2020-12-11 10:20  朝暮不思  阅读(83)  评论(0编辑  收藏  举报