通常我们使用的快速幂是以二为底的,这次就遇到了一道以10为底的快速幂题目;
先说下快速幂
long long power(long long a,long long b)///a是底数,b是次幂
{
long long ans=1;
for(;b!=0;b>>=1)
{
if(b&1) ans=(long long)ans*a%mod;
a=(long long)a*a%mod;
}
return ans;
}
在log时间内跑出a的b次幂
还有欧拉降幂 a^b%mod=a^(b%phi(mod))%mod,phi就是mod的欧拉返回值,也就是1——mod中有多少个与mod互质的数
long long phi(long long n) ///求欧拉函数值 返回值为多少个与n互质的数
{
long long ans=n,temp=n;
for(int i=2;i*i<=temp;i++)
{
if(temp%i==0)
{
ans-=ans/i;
while(temp%i== 0) temp/=i;
}
}
if(temp>1) ans-=ans/temp;
return ans;
}
还有逆元 比如/2 就是*0.5 但是不能用double会有误差尤其是在mod的情况下,所有就有了逆元
a在mod下的逆元为:power(a,phi(mod)-1);
上面都是与常数为例的,接下来就是矩阵形式的,这个引例就是斐波那契数列,你要求1e8以内的跑个递推循环,但是更大呢?
于是就有了矩阵快速幂 1 1 * fn = fn+1
1 0 * fn-1 fn
所以只要求那个矩阵的n-1次幂就可以了 于是就可以使用矩阵快速幂(以二为底)就是把b换成矩阵,保留矩阵答案就好,和快速幂本质上一毛一样
这次呢!碰到了一个以10为底的矩阵快速幂,因为他给的数有1e6位,本来想着是欧拉降幂,但是矩阵不可以使用欧拉降幂
于是就...
先说下题目吧 给个x0,x1 给个a ,b xn=a*xn-1+b*xn-2 再给个n求xn%mod为多少
十进制下的矩阵快速幂板子
#include<bits/stdc++.h>
using namespace std;
long long mod;
long long x0,x1,a,b;
string n;
long long power()
{
long long ans[3][3],k[3][3],h[3][3],h2[3][3];
ans[1][1]=k[1][1]=a;ans[1][2]=k[1][2]=b;ans[2][1]=k[2][1]=1;ans[2][2]=k[2][2]=0;
for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) h[i][j]=h2[i][j]=k[i][j];
for(int ii=n.size()-1;ii>=0;ii--)
{
int ddd=n[ii]-'0';
if(ddd)
{
for(int kkk=0;kkk<ddd;kkk++)
{
for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) h2[i][j]=ans[i][j];
ans[1][1]=h2[1][1]*k[1][1]+h2[1][2]*k[2][1];
ans[1][2]=h2[1][1]*k[1][2]+h2[1][2]*k[2][2];
ans[2][1]=h2[2][1]*k[1][1]+h2[2][2]*k[2][1];
ans[2][2]=h2[2][1]*k[1][2]+h2[2][2]*k[2][2];
for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) ans[i][j]%=mod;
}
//for(int i=1;i<=2;i++){for(int j=1;j<=2;j++)cout<<ans[i][j]<<' ';cout<<endl;}
}
for (int i = 1; i < 10; i++)
{
for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) h2[i][j]=k[i][j];
k[1][1]=h2[1][1]*h[1][1]+h2[1][2]*h[2][1];
k[1][2]=h2[1][1]*h[1][2]+h2[1][2]*h[2][2];
k[2][1]=h2[2][1]*h[1][1]+h2[2][2]*h[2][1];
k[2][2]=h2[2][1]*h[1][2]+h2[2][2]*h[2][2];
for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) k[i][j]%=mod;
}
for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) h[i][j]=k[i][j];
}
return ((ans[1][1]*x1)%mod+(ans[1][2]*x0)%mod)%mod;
}
int main()
{
ios::sync_with_stdio(false);
cin>>x0>>x1>>a>>b;
cin>>n>>mod;
if (n.size() == 1 && n[0] == '1')
{
cout<<x1<<endl;
return 0;
}
for(int i=n.size()-1;i>=0;i--)
{
if(n[i]!='0')
{
n[i]=n[i]-1;
for(int j=i+1;j<n.size();j++)
n[j]='9';
break;
}
}
for(int i=n.size()-1;i>=0;i--)
{
if(n[i]!='0')
{
n[i]=n[i]-1;
for(int j=i+1;j<n.size();j++)
n[j]='9';
break;
}
}
cout<<power()<<endl;
}
神奇的ios压缩时间