zoukankan      html  css  js  c++  java
  • 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
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    JavaScript总结(一)
    序列化函数
    random与os,sys模块
    认识模块
    时间模块
    日志处理
    异常处理
    类的约束
    反射
    区分函数以及方法
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14118984.html
Copyright © 2011-2022 走看看