【bzoj3329】Xorequ 矩阵快速幂

Description

img

Input

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

Output

2T行
第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

Sol

移项并转化得\(x\&2x=0\)

所以\(x\)相邻两项不能是俩1

枚举上一位是啥可得\(f[i]=f[i-1]+f[i-2]\)

第二问直接矩阵快速幂

第一问二进制拆分之后按位考虑计算贡献,出现两个相邻位之后break

并不需要数位dp。。。

Code

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll T,n,ans,m,F[70],w[70],P=1e9+7;
struct M
{
	ll m[2][2];
	M(){memset(m,0,sizeof(m));}
	friend M operator*(M a,M b)
	{
		M c;
		for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%P;
		return c;
	}
	friend M operator^(M a,ll b){M c;for(int i=0;i<2;i++) c.m[i][i]=1;for(;b;b>>=1,a=a*a) if(b&1) c=c*a;return c;}
}a,b;
int main()
{
	F[1]=1;for(int i=2;i<=64;i++) F[i]=F[i-1]+F[i-2];
	a.m[0][0]=a.m[0][1]=a.m[1][0]=1;
	for(scanf("%lld",&T);T--;printf("%lld\n%lld\n",ans-1,b.m[0][0]))
	{
		scanf("%lld",&n);++n;b=a^n;m=0;
		while(n) w[++m]=n&1,n>>=1;w[m+1]=ans=0;
		for(int i=m;i;i--){if(w[i]) ans+=F[i+1];if(w[i+1]&&w[i]) break;}
	}
}
posted @ 2018-08-14 20:53  CK6100LGEV2  阅读(107)  评论(0编辑  收藏  举报