题目网址:点击进入
Problem Description
Farmer John likes to play mathematics games with his N cows. Recently, they are attracted by recursive sequences. In each turn, the cows would stand in a line, while John writes two positive numbers a and b on a blackboard. And then, the cows would say their identity number one by one. The first cow says the first number a and the second says the second number b. After that, the i-th cow says the sum of twice the (i-2)-th number, the (i-1)-th number, and i4. Now, you need to write a program to calculate the number of the N-th cow in order to check if John’s cows can make it right.
Input
The first line of input contains an integer t, the number of test cases. t test cases follow.
Each case contains only one line with three numbers N, a and b where N,a,b < 231 as described above.
Output
For each test case, output the number of the N-th cow. This number might be very large, so you need to output it modulo 2147493647.
Sample Input
2
3 1 2
4 1 10
Sample Output
85
369
Hint
In the first case, the third number is 85 = 21十2十3^4.
In the second case, the third number is 93 = 21十1*10十3^4 and the fourth number is 369 = 2 * 10 十 93 十 4^4.
大致题意:
第一行给出 t ,接下来 t 行,每行三个数 n , a , b ,此时 f (1) = a ,f (2) = b,求 f(n)
f (n) = 2* f(n-2) + f(n-1) +n^4
思路:
第一眼递推式?看看数据可能会爆时间(本人不会算复杂度),我们一般会由递推公式联想到矩阵快速幂,那基本思路就来了
此题的关键在于矩阵A的建立
知f(n) = 2 x f(n-2) + f(n-1) + n^4
且f(n+1) = 2 x f(n-1) + f(n) + (n+1)^4
拆f(n+1) = 2 x f(n-1) + f(n) + n ^4 + 4 * n ^3 + 6 * n ^2 + 4 * n ^1 + 1
因为 f(n) 是1x7矩阵,f(n+1)也是,f(n) x A = f(n+1)
由此我们不难看出A是一个7x7矩阵
设f(n)矩阵为 [f(n-2),f(n-1),n^4,?,?,?,?]
这里我们只知道为1x7矩阵,但只知道f(n)的递推式的三个,后面四个先用?代替
设f(n+1)矩阵为 [f(n-1),f(n),(n+1)^4,?,?,?,?]同上
设A矩阵为
由f(n) x A = f(n+1)不难推出a,b,c,d为0,2,1,1,而第一列其余为0
此时A继续设置为
知f(n) = 2 x f(n-2) + f(n-1) + n^4
且f(n+1) = 2 x f(n-1) + f(n) + (n+1)^4
拆f(n+1) = 2 x f(n-1) + f(n) + n ^4 + 4 * n ^3 + 6 * n ^2 + 4 * n ^1 + 1
从这里我们不难看出
(n+1)^4= n ^4 + 4 * n ^3 + 6 * n ^2 + 4 * n ^1 + 1
每一个n+1的次方与上一层的n次方有很大关系,所以我们不妨设置
f(n)矩阵为 [f(n-2),f(n-1),n ^4,n ^3,n ^2,n ^1,n ^0]
f(n+1)矩阵为 [f(n-1),f(n),n+1 ^4,n+1 ^3,n+1 ^2,n+1 ^1,n+1 ^0]
由此我们不难得出a,b,c,d,e为1,4,6,4,1(多次项展开)
因为第三元素的n+1 ^4和上述同道理,故abcde右边一列与之一样
又有
(n+1)^3= n ^3 + 3 * n ^2 + 3 * n ^1 + 1
(n+1)^2= n ^2 + 2 * n ^1 + 1
(n+1)^1= n ^1 + 1
(n+1)^0= 1
所以很容易可以得到A矩阵的全部为
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long int LLD;
LLD mood=2147493647;
LLD n,a,b;
struct mat
{
LLD a[7][7];
};
mat buildans(LLD a,LLD b)
{
mat res;
memset(res.a,0,sizeof(res.a));
res.a[0][0]=a,res.a[0][1]=b;
LLD num=16;
for (LLD i=2; i<7; i++)
{
res.a[0][i]=num;
num=num/2;
}
return res;
}
mat buildmat()
{
mat res;
memset(res.a,0,sizeof(res.a));
res.a[2][1]=res.a[1][0]=1;
for (LLD i=1; i<7; i++)
{
res.a[i][i]=res.a[6][i]=1;
}
res.a[5][4]=res.a[0][1]=2;
res.a[4][3]=res.a[5][3]=3;
res.a[3][1]=res.a[3][2]=4;
res.a[5][1]=res.a[5][2]=4;
res.a[4][1]=res.a[4][2]=6;
return res;
}
mat matmul1(mat x,mat y)
{
mat res;
memset(res.a,0,sizeof(res.a));
for (LLD i=0; i<7; i++)
{
for (LLD j=0; j<7; j++)
{
res.a[0][i]=(res.a[0][i]+x.a[0][j]*y.a[j][i])%mood;
}
}
return res;
}
mat matmul2(mat x,mat y)
{
mat res;
memset(res.a,0,sizeof(res.a));
for (LLD i=0; i<7; i++)
{
for (LLD j=0; j<7; j++)
{
for(int k=0; k<7; k++)
{
res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%mood;
}
}
}
return res;
}
void matpow(LLD n)//矩阵快速幂
{
mat ans;//基本的1x7矩阵
ans=buildans(a,b);//初始化基本矩阵
mat res;//A矩阵
res=buildmat();//初始化A矩阵
while (n)
{
if (n%2==1)
{
ans=matmul1(ans,res);//基本矩阵xA矩阵
}
res=matmul2(res,res);//A矩阵平方
n=n/2;
}
printf("%lld\n",ans.a[0][1]%mood);
return ;
}
int main()
{
LLD t;
scanf("%lld\n",&t);
while (t--)
{
scanf("%lld %lld %lld",&n,&a,&b);
matpow(n-2);
}
return 0;
}