bzoj3329: Xorequ

首先画下柿子

x^(2x+x)=2x

假如x能够把括号里的x消掉,那么2x+x是不能在进位的,而2x是x<<1啊,所以满足条件的x没有相邻两位同时是1

遂数位DP解决,对于第二个问矩乘加速

第n次1LL<<i没打LL见祖宗

 

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;

LL f[110][2];
void solve1(LL n)
{
    int p=0;LL k=n;
    while(k>0)p++,k/=2;
    
    LL ans=0;
    for(int i=p;i>=1;i--)
        if(n&(1LL<<i-1))
        {
            ans+=f[i][0];
            if(n&(1LL<<i)){ans--;break;}
        }
    ans++;
    printf("%lld\n",ans-1);
}

struct Matrix
{
    LL mp[4][4];
    Matrix(){memset(mp,0,sizeof(mp));}
    friend Matrix operator *(Matrix a,Matrix b)
    {
        Matrix c;
        for(int i=1;i<=2;i++)
            for(int j=1;j<=2;j++)
                for(int k=1;k<=2;k++)
                    c.mp[i][j]=(c.mp[i][j]+a.mp[i][k]*b.mp[k][j])%mod;
        return c;
    }
};
void solve2(LL n)
{
    Matrix ans,A;n--;
    ans.mp[1][1]=1,ans.mp[1][2]=1;
    A.mp[1][1]=1,A.mp[1][2]=1,A.mp[2][1]=1;
    while(n!=0)
    {
        if(n%2==1)ans=ans*A;
        A=A*A;n/=2;
    }
    printf("%lld\n",(ans.mp[1][1]+ans.mp[1][2])%mod);
}

int main()
{
    f[1][0]=1,f[1][1]=1;
    for(int i=2;i<=62;i++)
        f[i][0]=f[i-1][0]+f[i-1][1], f[i][1]=f[i-1][0];
    
    int T;
    scanf("%d",&T);
    while(T--)
    {
        LL n;
        scanf("%lld",&n);
        solve1(n);
        solve2(n);
    }
    return 0;
}

 

posted @ 2018-10-18 15:32  AKCqhzdy  阅读(160)  评论(0编辑  收藏  举报