题目链接 : 4954:矩阵游戏 (tzcoder.cn)矩阵游戏 4954:矩阵游戏 (tzcoder.cn)
f[i][m]=f[i][1]*a^(m-1)+b∗(a^(m-2)+a^(m-3)+...+a^0)。
f[i+1][1]=c*f[i][m]+d.
合并上面两式
f[i][1]=c*f[i-1][1]*a^(m-1)+c*b∗(a^(m-2)+a^(m-3)+...+a^0)+d。
sa=a^(m-1);sb=(a^(m-2)+a^(m-3)+...+a^0);
f[i][m]=sa(c*f[i-1][m]+d)+sb;
由于指数非常大,我们运用费马小定理
a^(p - 1) ≡ 1 (mod p)
a^(m - 1) ≡ a^((m - 1) mod (p - 1)) (mod p)
(a^(m-2)+a^(m-3)+...+a^0)==a^(m-1)/(a-1)
求(a^(m-2)+a^(m-3)+...+a^0)可以用逆元
还要注意过程中有等比数列求和所以a==1要特判。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
char s[1000007];
ll ksm(ll x, ll y)
{
long long res = 1;
while (y)
{
if (y % 2)
res = res * x % mod;
y /= 2;
x = x * x % mod;
}
return res;
}
void getread(ll &x, ll &y)
{
scanf("%s", s);
int n = strlen(s);
for (int i = 0; i < n; i++)
{
x = (x * 10 + s[i] - '0') % (mod - 1);
y = (y * 10 + s[i] - '0') % mod;
}
}
ll ny(ll x)
{
return ksm(x, mod - 2);
}
ll getsum(ll q, ll n) // 求和
{
if (q == 1)
return n;
return ((ksm(q, n) - 1 + mod) % mod) * ny(q - 1) % mod;
}
void solve()
{
ll n = 0, nn = 0, m = 0, mm = 0;
getread(n, nn);
getread(m, mm);
n = (n - 1 + mod) % mod;
nn = (nn - 1 + mod) % mod;
m = (m - 1 + mod) % mod;
mm = (mm - 1 + mod) % mod;
ll a, b, c, d;
scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
ll sa = ksm(a, m);
ll sb, sc, sd;
if (a == 1)
{
sb = b * getsum(1, mm) % mod;
}
else
{
sb = b * getsum(a, m) % mod;
}
sc = c * sa % mod;
sd = (d * sa + sb) % mod;
ll k1, k2;
k1 = ksm(sc, n);
if (sc == 1)
{
k2 = sd * getsum(sc, nn) % mod;
}
else
{
k2 = sd * getsum(sc, n) % mod;
}
printf("%lld", (k1 * (sa + sb) + k2) % mod);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;
// cin >> T;
while (T--)
solve();
return 0;
}