转化一下式子变为x^2x=3x即x^2x=x+2x,那么显然x满足x和2x的二进制每一位不全为1,也就是x不存在某相邻的两位都是1。
对于第一问,令f[i][j][k]表示前i位,状态为j,最后一位为k的答案。j=0表示前i位<n,否则不作要求。转移一下即可。
第二问直接矩阵乘法加速即可。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 1000000007
#define ll long long
using namespace std;
ll n,m,f[105][2][2]; int a[105];
void ad(int &x,int y){ x+=y; if (x>=mod) x-=mod; }
struct matrix{ int p[2][2]; }b,c;
matrix tms(matrix x,matrix y){
matrix z; int i,j,k;
memset(z.p,0,sizeof(z.p));
for (i=0; i<2; i++)
for (j=0; j<2; j++)
for (k=0; k<2; k++) ad(z.p[i][k],(ll)x.p[i][j]*y.p[j][k]%mod);
return z;
}
int main(){
int cas; scanf("%d",&cas);
while (cas--){
scanf("%lld",&n); int i,j,k,len=0;
for (m=n+1; m; m>>=1) a[++len]=m&1;
memset(f,0,sizeof(f));
f[1][1][0]=f[1][1][1]=1; if (a[1]) f[1][0][0]=1;
for (i=2; i<=len; i++)
for (j=0; j<2; j++)
for (k=0; k<=max(j,a[i]); k++){
f[i][j][k]+=f[i-1][j|(k<a[i])][0];
if (!k) f[i][j][k]+=f[i-1][j|(k<a[i])][1];
}
printf("%lld\n",f[len][0][0]+f[len][0][1]-1);
b.p[0][0]=c.p[0][0]=c.p[0][1]=c.p[1][0]=1;
b.p[0][1]=b.p[1][0]=b.p[1][1]=c.p[1][1]=0;
for (; n; n>>=1,c=tms(c,c)) if (n&1) b=tms(b,c);
printf("%d\n",(b.p[0][0]+b.p[0][1])%mod);
}
return 0;
}
by lych
2016.4.21