2017 Multi-University Training Contest - Team 2 - 1006
HDU-6050 Funny Function
题意:
给出n, m
n代表
Fi,j
等于上一行从j开始往后n个元素的和
然后求第m行第一个元素
Fm,1
的值
思路:
先证
Fi,j=Fi,j−1+2∗Fi,j−2
这里用数学归纳法来证明
取 i = 2 ,n = 1
则 F2,j=F1,j 可以推出 F2,j=F2,j−1+2∗F2,j−2
假设 n = x 时 F2,j=F2,j−1+2∗F2,j−2 成立
即 ∑j+2+x−1k=jF1,k=∑j+1+x−1k=j+1F1,k+2∗∑j+x−1k=jF1,k - - - - - - ① 成立
当 n = x + 1 时
F2,j+2=∑j+2+xk=j+2F1,k=∑j+2+x−1k=j+2F1,k+F1,j+2+x
F2,j+1=∑j+1+xk=j+1F1,k=∑j+1+x−1k=j+1F1,k+F1,j+1+x
F2,j=∑j+xk=jF1,k=∑j+x−1k=jF1,k+F1,j+x
由题目中 F1,j=F1,j−1+2∗F1,j−2 得出 F1,j+2=F1,j+1+2∗F1,j
又因为 ① 所以我们可以得出 F2,j=F2,j−1+2∗F2,j−2 在 n≥1 时成立
然后以此类推 i = 3, 4, 5, 6 ······ 时也成立
证毕
再证
∑jk=1Fi,k=Fi,j+1−Fi,1 ( j 为偶数时)
∑jk=1Fi,k=Fi,j+1+Fi,1−Fi,2 ( j 为奇数时)
由上一步的公式 Fi,j=Fi,j−1+2∗Fi,j−2 得
当 j 为偶数时
Fi,j+1=Fi,j+2∗Fi,j−1
Fi,j−1=Fi,j−2+2∗Fi,j−3
Fi,j−3=Fi,j−4+2∗Fi,j−5
······
Fi,3=Fi,2+2∗Fi,1
我们把等号左右分别加起来得到
Fi,j+1=Fi,j+Fi,j−1+Fi,j−2+⋅⋅⋅+Fi,2+2∗Fi,1
=Fi,j+Fi,j−1+Fi,j−2+⋅⋅⋅+Fi,2+Fi,1+Fi,1
=∑jk=1Fi,j+Fi,1
移项得 ∑jk=1Fi,k=Fi,j+1−Fi,1 ( j 为偶数时)
当 j 为奇数时
Fi,j+1=Fi,j+2∗Fi,j−1
Fi,j−1=Fi,j−2+2∗Fi,j−3
Fi,j−3=Fi,j−4+2∗Fi,j−5
······
Fi,4=Fi,3+2∗Fi,2
把等号左右分别加起来得
Fi,j+1=Fi,j+Fi,j−1+Fi,j−2+⋅⋅⋅+Fi,2+2∗Fi,2
等号两边分别加上 Fi,1 得
Fi,j+1+Fi,1=Fi,j+Fi,j−1+Fi,j−2+⋅⋅⋅+Fi,2+Fi,2+Fi,1+Fi,2
Fi,j+1+Fi,1=∑jk=1Fi,k+Fi,2
移项得 ∑jk=1Fi,k=Fi,j+1+Fi,1−Fi,2 ( j 为奇数时)
证毕
然后是
(Fm,1,Fm,2)=(F1,1,F1,2)(An−B0)m−1 ( n 为偶数时)
(Fm,1,Fm,2)=(F1,1,F1,2)(An−B1)m−1 ( n 为奇数时)
由第一步的递推公式 Fi,j=Fi,j−1+2∗Fi,j−2 来构造矩阵
(Fi,j−1,Fi,j)=(Fi,j−2,Fi,j−1)∗(0121)
令 A=(0121)
则 (Fi,j,Fi,j+1)=(Fi,j−1,Fi,j)∗A=(Fi,1,Fi,2)∗Aj−1 - - - - - - ①
当 n 为偶数时
由题目所给公式可得
Fi,1=∑nk=1Fi−1,k 由第二步公式得
=Fi−1,n+1−Fi−1,1
Fi,2=∑n+1k=1Fi−1,k−Fi−1,1 由第二步公式得
=Fi−1,n+2+Fi−1,1−Fi−1,2−Fi−1,1
=Fi−1,n+2−Fi−1,2
则可以得出
(Fi,1,Fi,2)=(Fi−1,n+1−Fi−1,1,Fi−1,n+2−Fi−1,2)
=(Fi−1,n+1,Fi−1,n+2)−(Fi−1,1,Fi−1,2) 令①中 j = n + 1 带入得
=(Fi−1,1,Fi−1,2)∗An−(Fi−1,1,Fi−1,2)∗(1001)
令 B0=(1001) 则可以得到
(Fi,1,Fi,2)=(Fi−1,1,Fi−1,2)∗(An−B0)
而这又是一个递推关系,我们就可以得到
(Fm,1,Fm,2)=(F1,1,F1,2)∗(An−B0)m−1
当 n 为奇数时
Fi,1=∑nk=1Fi−1,k 由第二步公式得
=Fi−1,n+1+Fi−1,1−Fi−1,2
Fi,2=∑n+1k=1Fi−1,k−Fi−1,1 由第二步公式得
=Fi−1,n+2−Fi−1,1−Fi−1,1
=Fi−1,n+2−2∗Fi−1,1
则可以得出
(Fi,1,Fi,2)=(Fi−1,n+1+Fi−1,1−Fi−1,2,Fi−1,n+2−2∗Fi−1,1)
=(Fi−1,n+1,Fi−1,n+2)−(−Fi−1,1+Fi−1,2,2∗Fi−1,1) 令①中 j = n + 1 带入得
=(Fi−1,1,Fi−1,2)∗An−(Fi−1,1,Fi−1,2)∗(−1120)
令 B1=(−1120) 则可以得到
(Fi,1,Fi,2)=(Fi−1,1,Fi−1,2)∗(An−B1)
而这又是一个递推关系,我们就可以得到
(Fm,1,Fm,2)=(F1,1,F1,2)∗(An−B1)m−1
综上我们得出了两个公式
(Fm,1,Fm,2)=(F1,1,F1,2)(An−B0)m−1 ( n 为偶数时)
(Fm,1,Fm,2)=(F1,1,F1,2)(An−B1)m−1 ( n 为奇数时)
及公式中的 A,B0,B1 矩阵
A=(0121) B0=(1001) B1=(−1120)
然后就可以愉快的使用矩阵快速幂求解了
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int mod = 1e9 + 7;
struct S
{
long long a[2][2];
};
S cheng(S a, S b) // 矩阵乘法
{
S temp;
memset(temp.a, 0, sizeof(temp.a));
for(int i = 0; i < 2; ++i)
{
for(int j = 0; j < 2; ++j)
{
for(int k = 0; k < 2; ++k)
{
temp.a[i][j] += a.a[i][k] * b.a[k][j] % mod;
temp.a[i][j] %= mod;
}
}
}
return temp;
}
int main()
{
S a, b[2], f, temp;
int t;
long long n, m, n1;
while(~scanf("%d", &t))
{
while(t--)
{
memset(a.a, 0, sizeof(a.a)); // 初始化 A B0 B1 矩阵
memset(b[0].a, 0, sizeof(b[0].a));
memset(b[1].a, 0, sizeof(b[1].a));
memset(f.a, 0, sizeof(f.a));
memset(temp.a, 0, sizeof(temp.a));
a.a[0][1] = b[1].a[0][1] = 2;
a.a[1][0] = a.a[1][1] = b[0].a[0][0] = b[0].a[1][1] = b[1].a[1][0] = f.a[0][0] = f.a[0][1] = 1;
b[1].a[0][0] = -1;
temp.a[0][0] = temp.a[1][1] = 1;
scanf("%lld%lld", &n, &m);
n1 = n;
while(n) // temp保存A^n的值
{
if(n & 1)
{
temp = cheng(temp, a);
}
n >>= 1;
a = cheng(a, a);
}
for(int i = 0; i < 2; ++i) // A 保存 A^n - B 的值
{
for(int j = 0; j < 2; ++j)
{
a.a[i][j] = temp.a[i][j] - b[n1 % 2].a[i][j];
}
}
memset(temp.a, 0, sizeof(temp.a));
temp.a[0][0] = temp.a[1][1] = 1;
--m;
while(m) // 求(A^n - B)^(m - 1)保存在temp中
{
if(m & 1)
{
temp = cheng(temp, a);
}
m >>= 1;
a = cheng(a, a);
}
f = cheng(f, temp); // 最后再用 {F(1,1) = 1 , F(1,2) = 1 } 乘上 (A^n - B)^(m - 1)
cout << f.a[0][0] << endl;
}
}
return 0;
}