求ab时,将b化为二进制考虑,从而大幅减少时间复杂度。快速幂的时间复杂的为O(log2n)一般的幂乘运算为O(n)。
例如求412.12的二进制是1100,即12=123+122+021+020.也就是说单从12的二进制1100来看,后面两个0对结果来说是无意义的。所以我们只需在有1的位置上将结果保持就可以了,再使用>>运算符进行移位运算,累乘进行进位。
大概是这种感觉:
ll dpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans%mod;
}
快速幂还可以在运算的过程中就进行取模,这样就可以解决数据范围超过long long但对结果要求取模的问题.
博主的个人A题合集(仅供参考,不喜勿喷)
与快速幂相同,只是把求数的幂运算换成了矩阵。
struct mar
{
ll x[2][2];
};
mar Mul(mar a,mar b,ll n)//自定义矩阵相乘运算
{
mar c;
memset(c.x,0,sizeof(c.x));
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
for(int k=0; k<n; k++)
c.x[i][j] = (c.x[i][j] + (a.x[i][k] * b.x[k][j]) % mod) % mod;
return c;
}
mar quick_matrix(mar m,ll n)//矩阵快速幂
{
mar res;
for(int i=0; i<2; i++)//初始化一个单位矩阵,相当于数乘的1
res.x[i][i]=1;
res.x[1][0]=0;
res.x[0][1]=0;
while(n)
{
if(n&1)
res=Mul(res,m,2);
m=Mul(m,m,2);
n>>=1;
}
return res;
}
帮我求一下斐波那契数列吧
描述:
AYY小朋友对斐波那契数非常感兴趣,他知道f[1]=1,f[2]=1,并且从第三个斐波那契数开始f[n]=f[n-2]+f[n-1](n>=3),可是AYY小朋友只会计算前十个斐波那契数,因此他向你请教,让你帮忙计算第N个斐波那契数是多少,但是由于结果非常大,只需告诉他对1000000007取模的结果。
输入:
多组测试数据
每行一个n(1<=n<=2^32-1)
输出:
输出第n个斐波那契数的结果(对1000000007取模)
样例:
[input]:
1
10
100
1000
10000
[output]:
1
55
687995182
517691607
271496360
解题代码:
#include
using namespace std;
typedef long long ll;
const int mod=1000000007;
struct mar
{
ll x[2][2];
};
mar Mul(mar a,mar b,ll n)
{
mar c;
memset(c.x,0,sizeof(c.x));
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
for(int k=0; k<n; k++)
c.x[i][j] = (c.x[i][j] + (a.x[i][k] * b.x[k][j]) % mod) % mod;
return c;
}
ll quick_matrix(mar m,ll n)
{
mar res;
for(int i=0; i<2; i++)
res.x[i][i]=1;
res.x[1][0]=0;
res.x[0][1]=0;
while(n)
{
if(n&1)
res=Mul(res,m,2);
m=Mul(m,m,2);
n>>=1;
}
/*for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
cout<
ll ans=(res.x[0][0]+res.x[1][0])%mod;
return ans;
}
int main()
{
ll n;
while(cin>>n)
{
mar p;
if(n>2)
{
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
p.x[i][j]=1;
p.x[1][1]= {0};
cout<<quick_matrix(p,n-2)<<endl;
}
else
cout<<1<<endl;
}
return 0;
}