• BZOJ 3329. Xorequ


    传送门

    看到方程感觉比较奇怪,变一下:

    注意到 $3x=(x<<1)+x$

    那么 $x ext{ xor } ((x<<1)+x)=(x<<1) $

    左右同时异或 $x$ ,得到 $(x<<1)+x=(x<<1) ext{ xor } x$

    因为 $ ext{xor}$ 是不进位的加法

    发现当且仅当 $(x<<1)$ 和 $x$ 二进制下同一位不存在都是 $1$ 的情况上式才成立

    所以就是求二进制下没有相邻的 $1$ 的数的个数,显然是可以 $dp$ 的

    首先设 $f[i][0/1]$ 表示前 $i$ 位,第 $i$ 位为 $0/1$ 时合法的方案数(此时没考虑 $n$ 的限制)

    然后对 $n$ 数位 $dp$ ,求出第 $1$ 问

    对于第二问直接对 $f$ 矩阵加速即可

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    inline ll read()
    {
        ll x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int mo=1e9+7;
    ll T,n,ans1;
    ll f[107][2];
    void dfs(int p)
    {
        if(p<0) { ans1++; return; }
        if(n&(1ll<<p))
        {
            ans1+=f[p][0];
            if(p<62 && (n&(1ll<<p+1)) ) return;
            dfs(p-1);
        }
        else dfs(p-1);
    }
    inline int fk(int x) { return x>=mo ? x-mo : x; }
    struct Matrix {
        int a[2][2];
        Matrix () { memset(a,0,sizeof(a)); }
        inline Matrix operator * (const Matrix &tmp) const {
            Matrix res;
            for(int i=0;i<2;i++)
                for(int j=0;j<2;j++)
                    res.a[i][j]=fk(1ll*a[i][0]*tmp.a[0][j]%mo+1ll*a[i][1]*tmp.a[1][j]%mo);
            return res;
        }
    }Ans,F;
    inline Matrix ksm(Matrix x,ll y)
    {
        Matrix res; res.a[0][0]=res.a[1][1]=1;
        while(y)
        {
            if(y&1) res=res*x;
            x=x*x; y>>=1;
        }
        return res;
    }
    int main()
    {
        T=read();
        f[0][0]=f[0][1]=1;
        for(int i=1;i<=62;i++)
            f[i][0]=f[i-1][0]+f[i-1][1],
            f[i][1]=f[i-1][0];
        while(T--)
        {
            n=read(); dfs(62);
            Ans.a[0][0]=Ans.a[0][1]=1;
            F.a[0][0]=F.a[0][1]=1; F.a[1][0]=1;
            Ans=Ans*ksm(F,n);
            printf("%lld
    %d
    ",ans1-1,Ans.a[0][0]);
            ans1=0;
        }
        return 0;
    }
  • 相关阅读:
    如何在Ubuntu Server 18.04上安装Microsoft的Procmon
    如何在Ubuntu 20.04上安装Wine 5.0
    如何在Kali Linux 2020中启用SSH服务
    如何在Ubuntu 20.04 LTS Focal Fossa上安装Apache Groovy
    如何使用命令在Ubuntu 20.04 Linux上安装Vmware Tools
    在Ubuntu 20.04 LTS Focal Fossa上安装Zabbix Agent
    hdu 2089 不要62
    hdu 2093 成绩排名
    hdu 2104 hide handkerchief
    leetcode147对链表进行插入排序
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11562524.html
Copyright © 2020-2023  润新知