BZOJ 3329 Xorequ

Posted on 2017-03-15 10:55  ziliuziliu  阅读(98)  评论(0编辑  收藏  举报

x^2x=3x,x+2x=3x。而异或是不进位的加法。

所以x+2x不能进位。也就是说x中没有相邻的两个1。

对于第一问可以数位dp,对第二问可以矩阵快速幂。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 1000000007
using namespace std;
long long t,n,ans1,ans2,ret=0,bit[100],dp[100][2];
struct matrix
{
    long long t[3][3];
    friend matrix operator *(const matrix &x,const matrix &y)
    {
        matrix ans;
        for (long long i=1;i<=2;i++)
            for (long long j=1;j<=2;j++)    
                ans.t[i][j]=0;
        for (long long i=1;i<=2;i++)
            for (long long j=1;j<=2;j++)
                for (long long k=1;k<=2;k++)
                    ans.t[i][j]=(ans.t[i][j]+(x.t[i][k]*y.t[k][j])%mod)%mod;
        return ans;
    }
}base[100],ans;
void get_bit(long long x)
{
    ret=0;
    while (x) {bit[++ret]=x&1;x>>=1;}
}
long long digit_dp(long long now,long long pre,bool flag)
{
    if (!now) return 1;
    if (!flag && dp[now][pre]) return dp[now][pre];
    long long ret=0,up=flag?bit[now]:1;
    for (long long i=0;i<=up;i++)
    {
        if (pre && i) continue;
        ret+=digit_dp(now-1,i,flag && (i==up));
    }
    if (!flag) dp[now][pre]=ret;
    return ret;
}
void work1()
{
    get_bit(n);
    ans1=digit_dp(ret,0,1);
}
void work2()
{
    ans.t[1][1]=ans.t[1][2]=1;
    long long ret=0,y=n-1;
    while (y)
    {
        if (y&1) ans=ans*base[ret];
        ret++;y>>=1;
    }
    ans2=(ans.t[1][1]+ans.t[1][2]+1)%mod;
}
int main()
{
    scanf("%lld",&t);
    base[0].t[1][1]=base[0].t[1][2]=base[0].t[2][1]=1;base[0].t[2][2]=0;
    for (long long i=1;i<=64;i++) base[i]=base[i-1]*base[i-1];
    for (long long i=1;i<=t;i++)
    {
        scanf("%lld",&n);
        work1();work2();
        printf("%lld\n%lld\n",ans1-1,ans2-1);
    }
    return 0;
}