3329: Xorequ

题目链接

题目大意:给定方程 x xor 3x=2x ,给定正整数n
(1)求小于等于 n 的正整数中有多少个满足该方程
(2)求小于等于2n的正整数中有多少个满足该方程,答案模 1e9+7

题解:性质: a xor b=ca xor c=b
x xor 3x=2x 变成 x xor 2x=3x
由于异或本质上是不进位加法,有性质 a &b=0a& b=a+b

2x 相当于 x<<1 ,条件最后变成 x 的二进制位上没有相邻的1

第一问直接数位dp

第二问:设 g(i) 表示 i 位的满足条件的x个数
按二进制位易知 g(i)=g(i1)+g(i2) ,同时有 g(0)=0,g(1)=1

2n 拆分成 2n 一个数和所有二进制小于等于 n 位的数

ans=i=1ng(i),注意到 2n 满足条件,再 +1
用一下fib的求和公式即可 log 求解

我的收获:2333

#include <bits/stdc++.h>
using namespace std;

#define rep(i,x) for(int i=0;i<x;i++) 
const int N=2;
const int P=1e9+7;

int T;
int bit[66];
long long n,f[66][2];

struct Matrix{
    int x,y;long long v[N][N];
    long long *operator [] (int x){return v[x];}
    Matrix(int _x,int _y,int w=0){
        x=_x,y=_y;
        rep(i,N) rep(j,N) v[i][j]=(i==j)?w:0;
    }
};

Matrix operator * (Matrix a,Matrix b){
    Matrix c(a.x,b.y);
    rep(i,a.x) rep(j,b.y) rep(k,a.y) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%P;
    return c;
}

Matrix operator ^ (Matrix a,long long b){
    Matrix c(a.x,a.y,1);
    for(;b;b>>=1,a=a*a)
    if(b&1) c=c*a;
    return c;
}

Matrix A(N,N),B(1,N);

long long dfs(int x,int s,int e)
{
    if(!x) return 1; 
    if(!e&&f[x][s]!=-1) return f[x][s];
    long long ret=0;int u=e?bit[x]:1;
    for(int i=0;i<=u;i++){
        if(s&&i) continue;
        ret+=dfs(x-1,i,e&&i==u); 
    }
    return !e?f[x][s]=ret:ret;
}

long long calc(long long x)
{
    int len=0;memset(f,-1,sizeof(f));
    while(x) bit[++len]=x%2,x/=2;
    return dfs(len,0,1);
}

void MakeMatrix()
{
    A[0][0]=A[0][1]=A[1][0]=1;
    A[1][1]=0;
    B[0][1]=0,B[0][0]=1;
}

void fib()
{
    MakeMatrix();
    A=A^(n+1);A=A*B;
    printf("%lld\n%lld\n",calc(n)-1 ,A[0][0]);
}

void work()
{
    cin>>n;
    fib();
}

int main()
{
    cin>>T;
    while(T--) work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值