链接:https://ac.nowcoder.com/acm/contest/885/B
这个题很简单就能想到构建一个矩阵,然后求矩阵快速幂。
不过因为十进制数太大,只能表示为一个字符串,所以不容易进行二进制拆分。但是根据矩阵快速幂的原理,我们写成十进制也是可以的。这样只需每次判断尾数是否为为10的倍数,是10的倍数就让a=a^10,b/=10.否则让ans*=a^(b%10).
例子:5^1058=(5)^8 * (5^10)^5 * (5^100)^0 * (5^1000)^1
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int T;
LL a, b, c, d, f0, f1, n,mod;
struct node
{
LL Map[2][2];
};
string s;
node mul(node a, node b)
{
node tmp;
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++)
{
tmp.Map[i][j] = 0;
for(int k = 0; k < 2; k++)
{
tmp.Map[i][j] += a.Map[i][k] * b.Map[k][j];
tmp.Map[i][j] %= mod;
}
}
return tmp;
}
node qp(node a,int b)//2进制矩阵快速幂
{
node ans;
memset(ans.Map,0,sizeof(ans.Map));
for(int i=0;i<2;++i) ans.Map[i][i]=1;
while(b)
{
if(b&1)
ans=mul(ans,a);
a=mul(a,a);
b>>=1;
}
return ans;
}
node calc(node a,string s)//10进制矩阵快速幂
{
node ans;
memset(ans.Map,0,sizeof(ans.Map));
for(int i=0;i<2;++i) ans.Map[i][i]=1;
for(int i=s.size()-1;i>=0;--i)
{
int rem=s[i]-'0';
if(rem)//末尾不为。就先把答案乘到ans上
{
ans=mul(ans,qp(a,rem));
}
a=qp(a,10);//另一部分缩小幂次,增大底数
}
return ans;
}
void print(node a)
{
puts("---------");
for(int i=0;i<2;++i){
for(int j=0;j<2;++j){
cout<<a.Map[i][j]<<" ";
}
cout<<endl;
}
puts("---------");
}
int main()
{
LL times;
cin>>f0>>f1>>a>>b;
cin>>s;
cin>>mod;
node arr, arr2;
arr2.Map[0][0] = a;
arr2.Map[0][1] = b;
arr2.Map[1][0] = 1;
arr2.Map[1][1] = 0;
arr.Map[0][0] = 0;
arr.Map[0][1] = f1;
arr.Map[1][0] = 0;
arr.Map[1][1] = f0;
node p;
p = calc(arr2,s);
// print(p);
// print(qp(arr2,10));
p = mul(p, arr);
printf("%lld\n", p.Map[1][1]);
return 0;
}