[BZOJ3329] Xorequ

[BZOJ3329] Xorequ

Description

Input

第一行一个正整数,表示数据组数据 ,接下来T行每行一个正整数N

Output

2T行第2i-1行表示第i个数据中问题一的解,第2*i行表示第i个数据中问题二的解,

Sample Input

1
1

Sample Output

1
2

HINT

x=1与x=2都是原方程的根,注意第一个问题的解不要mod 10^9+7
1<=N<=10^18
1<=T<=1000

试题分析

由于我们有式子\(x\oplus 3x = 2x\),可以尝试进行推导。
由于\(x\oplus x = 0\)\(0 \oplus x = 0\),可推导出:$$x\oplus 2x = 3x$$
3x就相当于是x的二进制位上的所有1前面再加一个1,然后再考虑进位。
\(x\oplus 2x = 3x\),由于\(2x\)\(x\)右移一位,相当于效果与\(3x\)相同。
因此可以证明没有进位,也就是说一个数没有1的位相邻。
对于第二问,打一个表推推式子矩阵快速幂一下。

强行二合一

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
 
using namespace std;
#define LL long long
 
inline LL read(){
    LL x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const LL MAXN = 1000010;
const LL INF = 2147483600;
const LL Mod = 1e9+7;
 
LL N,K,M,P,TT;
LL a[101][101],b[101][101],c[101][101];
 
void Mul1(){
    memset(b,0,sizeof(b));
    for(LL i=1;i<=N;i++)
        for(LL j=1;j<=M;j++)
            for(LL k=1;k<=K;k++)
                b[i][j]+=a[i][k]*c[k][j]%Mod,b[i][j]%=Mod;
    for(LL i=1;i<=N;i++){
        c[i][1]=b[i][1];
    }
    return ;
}
void Mul2(){
    memset(b,0,sizeof(b));
    for(LL i=1;i<=N;i++)
        for(LL j=1;j<=N;j++)
            for(LL k=1;k<=N;k++)
                b[i][j]+=a[i][k]*a[k][j]%Mod,b[i][j]%=Mod;
    for(LL i=1;i<=N;i++){
        for(LL j=1;j<=N;j++)
            a[i][j]=b[i][j];
    }
    return ;
}
LL dp[67][2][2]; LL str[MAXN+1];LL cnt=0;
inline void split(LL x){
    while(x){
        str[++cnt]=(x&1);
        x=x>>1;
    } while(cnt<=64) str[++cnt]=0;
    //for(LL i=1;i<=cnt/2;i++) swap(str[i],str[cnt-i+1]);
    //for(int i=cnt;i>=1;i--) cout<<str[i]; cout<<endl;
}
LL ans;
 
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    int T=read(); dp[0][0][0]=1;
    for(LL i=0;i<65;i++){
        for(LL j=0;j<2;j++){
            for(LL k=0;k<2;k++){
                //cout<<dp[i][j][k]<<":"<<i<<" "<<j<<" "<<k<<endl;
                if(j==1&&k==1) continue;
                dp[i+1][0][j]+=dp[i][j][k];
                if(!j) dp[i+1][1][j]+=dp[i][j][k];
            }
        }
    } 
    while(T--){
        P=TT=read(); 
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        N=2; M=1; K=2;
        a[1][1]=a[1][2]=1; a[2][1]=1;
        c[1][1]=1; c[2][1]=1; ++P;
        while(P){
            if(P&1) Mul1(); P>>=1;
            Mul2();
        } N=TT; cnt=0;
        split(N); ans=0;
        for(LL i=cnt;i>=2;i--){
            if(str[i]==1)
                ans+=dp[i][0][0]+dp[i][0][1];
            if(str[i-1]==str[i]&&str[i-1]==1) {ans+=dp[i][1][0]; break;}
            if(i==2){++ans; ans+=str[i-1]; }
        } 
        if(N!=1) printf("%lld\n",ans-1);
        else printf("%lld\n",1LL);
        printf("%lld\n",c[2][1]%Mod);
    }
    return 0;
     
}
posted @ 2018-08-23 08:40  wxjor  阅读(273)  评论(0编辑  收藏  举报