Description
Input
第一行一个正整数,表示数据组数据 ,接下来T行
每行一个正整数N
Output
2*T行
第2*i-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^3x==2x → x^3x^x==2x^x → 3x^x^x==2x^x
→ 3x^0==2x^x → 3x==2x^x → x^2x==3x
而我们都知道x+2x==3x
,而^是二进制上不进位的加法,x^2x
的效果与x+2x
相同,说明
x
x
和任意一位上都不可能同时是1。然后
2x
2
x
是
x
x
左移一位,所以意味着不存在相邻的两位,满足这两位上都是1。于是我们就可以用数位DP来求取
x
x
的方案数。
表示第i位,上面为j(0或1),并且是否被约束。最后的答案就是f[cnt][0][0]+f[cnt][0][1]+f[cnt][1][0]+f[cnt][1][1]-1
(cnt表示x二进制下的位数,-1是因为要舍去0这种情况)
对于第二问我们要推一推结论,我们手算几个,设 f(x) f ( x ) 表示 2x 2 x 时的答案,则 f(0)=1,f(1)=2,f(2)=3,f(3)=5,f(5)=8…… f ( 0 ) = 1 , f ( 1 ) = 2 , f ( 2 ) = 3 , f ( 3 ) = 5 , f ( 5 ) = 8 … … 发现 f(x) f ( x ) 刚好满足斐波那契数列(只不过开头只有1个1),所以对于 f(n) f ( n ) 我们直接用矩阵乘法加速即可。
#include<bits/stdc++.h>
#define MD 1000000007
#define ll long long
using namespace std;
ll read(){
char c;ll x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
void print(ll x){
if(x/10) print(x/10);
putchar(x%10+'0');
}
ll T,n,cnt,ans,num[61],f[61][2][2],A[2][2],B[2][2],U[2][2];
void mul(ll a[][2],ll b[][2]){
for(ll i=0;i<2;i++)
for(ll j=0;j<2;j++){
ll res=0;
for(ll k=0;k<2;k++) res=(res+a[i][k]*b[k][j])%MD;
U[i][j]=res;
}
for(ll i=0;i<2;i++)
for(ll j=0;j<2;j++)
a[i][j]=U[i][j];
}
int main()
{
T=read();
while(T--){
memset(f,0,sizeof(f));
n=read();ll p=n;cnt=0;ans=0;
while(p){
cnt++;
if(p&1) num[cnt]=1;
else num[cnt]=0;
p/=2;
}
f[0][0][0]=1;
for(ll i=0;i<cnt;i++)
for(ll k=0;k<2;k++){
if(f[i][0][k]){
f[i+1][0][k|(0<num[cnt-i])]+=f[i][0][k];
if(k||num[cnt-i]==1)f[i+1][1][k]+=f[i][0][k];
}
if(f[i][1][k]){
f[i+1][0][k|(0<num[cnt-i])]+=f[i][1][k];
}
}
ans=(f[cnt][0][0]+f[cnt][0][1]+f[cnt][1][0]+f[cnt][1][1]);
print(ans-1);puts("");
A[0][0]=2;A[0][1]=1;A[1][0]=A[1][1]=0;B[0][0]=B[0][1]=B[1][0]=1;B[1][1]=0;
if(n==0){puts("1");continue;}
p=(n-1);
while(p){
if(p&1) mul(A,B);
mul(B,B);p/=2;
}
print(A[0][0]);puts("");
}
return 0;
}