-
1 1 5 7 5 13 10
样例输出
-
55
描述
小h很多朋友。他给第i个朋友分配了一个代号Ai,并使代号序列满足如下关系:
Ai = (k1 * Ai-1 + k2 * Ai-2) mod 1,000,000,007
现在小h忘记了第z个朋友的代号Az,但是他记得第x个朋友和第y个朋友的代号Ax和Ay。
小h很着急,向小y求助。小y很忙,把任务交给了你,希望你求出第z个朋友的代号。
输入
第一行共2个整数,k1,k2;
第二行共4个整数,x,y,Ax,Ay;
第三行共1个整数,z。
3<=x,y,z<=1018 0<=k1,k2<=105
输入数据保证有解,且解唯一
输出
共一行1个整数,Az。
xyz又那么大,明显矩阵快速幂。求第z项值就要知道初始的两个值才可以。那就是利用第x,y项来列方程求解了。
初始矩阵U为:
[ A1 A2]
[ 0 0]
递推矩阵I为:
[ 0 k2]
[ 1 k1]
当然不唯一,保证递推关系成立就可以了
其实U的A2为当前值,这是第二个,那么 U×I^(x - 2) 得到x项矩阵, U×I^(y-2)得到第y项矩阵,x,y项的值都知道了,乘一下列方程组
A1*x1 + A2*x2 = x
A1*y1 + A2*y2 = y
接下来消去一项求另一项,再带入求刚才消去的那一项。这个过程中的减法需要加mod再取模以免为负数,各种乘法都要乘一次取一次模,除法乘逆元,因为模的是指数,直接快速幂费马小定理求逆元。a^(p-2) = 1/a mod(p)。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
const int N = 1000001;
typedef long long ll;
using namespace std;
int mod = 1000000007;
struct Mat
{
ll a[2][2];
Mat()
{
memset(a, 0, sizeof(a));
}
void set0()
{
memset(a, 0, sizeof(a));
}
void set1()
{
set0();
for (int i = 0; i < 2; i++)
a[i][i] = 1;
}
Mat operator * (const Mat& b)const
{
Mat c;
c.set0();
for (int i = 0; i < 2; i++)
for (int k = 0; k < 2; k++)
if (a[i][k])
for (int j = 0; j < 2; j++)
{
c.a[i][j] = ( (a[i][k]*b.a[k][j])%mod + c.a[i][j] ) % mod;
}
return c;
}
};
Mat operator ^ (Mat a, ll x)
{
Mat ret;
ret.set1();
while (x)
{
if (x&1)
ret = ret * a;
x >>= 1;
a = a * a;
}
return ret;
}
ll Pow(ll a, ll x)
{
ll ret = 1;
a %= mod;
while (x)
{
if (x&1)
ret = (ret*a)%mod;
x >>= 1;
a = (a*a)%mod;
}
return ret;
}
int main()
{
ll k1, k2;
ll x, y, ax, ay, z;
while (cin >> k1 >> k2)
{
cin >> x >> y >> ax >> ay >> z;
Mat tx, ty, one;
one.a[0][0] = 0;
one.a[0][1] = k2;
one.a[1][0] = 1;
one.a[1][1] = k1;
ty = one ^ (y - 2);
tx = one ^ (x - 2);
ll &x1 = tx.a[0][1], &x2 = tx.a[1][1], &y1 = ty.a[0][1], &y2 = ty.a[1][1];
ll up = ((ax*y1%mod - x1*ay%mod) + mod)%mod;
ll a2 = up * Pow(( (x2*y1 % mod - x1*y2 % mod) + mod)%mod, mod - 2) %mod;
ll a1 = (ax - x2*a2%mod + mod)%mod;
a1 = a1 * Pow(x1, mod - 2) %mod;
Mat I;
I.a[0][0] = a1;
I.a[0][1] = a2;
I = I * (one ^ (z - 2));
cout<<I.a[0][1]<<endl;
}
return 0;
}