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

  显然当x中没有相邻的1时该式成立,看起来这也是必要的。

  于是对于第一问,数位dp即可。第二问写出dp式子后发现就是斐波拉契数列,矩阵快速幂即可。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define P 1000000007
#define ll long long
int T,num[100];
ll n,dp[100][2][2];
struct matrix
{
    int n,a[2][2];
    matrix operator *(const matrix&b) const
    {
        matrix c;c.n=n;memset(c.a,0,sizeof(c.a));
        for (register int i=0;i<n;i++)
            for (register int j=0;j<2;j++)
                for (register int k=0;k<2;k++)
                c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j]%P)%P;
        return c;
    }
}f,a;
ll solve1(ll n)
{
    memset(dp,0,sizeof(dp));
    int m=-1;
    while (n) num[++m]=n&1,n>>=1;
    dp[m+1][0][1]=1;
    for (int i=m;~i;i--)
    if (num[i])
    {
        dp[i][0][0]=dp[i+1][0][0]+dp[i+1][0][1]+dp[i+1][1][0]+dp[i+1][1][1];
        dp[i][1][0]=dp[i+1][0][0];
        dp[i][1][1]=dp[i+1][0][1];
    }
    else
    {
        dp[i][0][0]=dp[i+1][0][0]+dp[i+1][1][0];
        dp[i][0][1]=dp[i+1][0][1]+dp[i+1][1][1];
        dp[i][1][0]=dp[i+1][0][0];
    }
    return dp[0][0][0]+dp[0][0][1]+dp[0][1][0]+dp[0][1][1];
}
int solve2(ll n)
{
    a.n=2;a.a[0][0]=0;a.a[0][1]=a.a[1][0]=a.a[1][1]=1;
    f.n=1;f.a[0][0]=0,f.a[0][1]=1;
    for (;n;n>>=1,a=a*a) if (n&1) f=f*a;
    return f.a[0][1];
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj3329.in","r",stdin);
    freopen("bzoj3329.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    T=read();
    while (T--)
    {
        scanf(LL,&n);
        printf(LL,solve1(n)-1);
        printf("%d\n",solve2(n+1));
    }
    return 0;
}

 

posted @ 2018-09-21 18:22  Gloid  阅读(191)  评论(0编辑  收藏  举报