Recursive sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 132 Accepted Submission(s): 84
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.
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 369HintIn the first case, the third number is 85 = 2*1十2十3^4. In the second case, the third number is 93 = 2*1十1*10十3^4 and the fourth number is 369 = 2 * 10 十 93 十 4^4.
Source
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const UI Z = 2147493647;
const int G = 7;
struct MX
{
UI v[G][G];
void O() { MS(v, 0); }
void E() { MS(v, 0); for (int i = 0; i < G; ++i)v[i][i] = 1; }
void P()
{
for (int i = 0; i < G; ++i)
{
for (int j = 0; j < G; ++j)printf("%u ", v[i][j]); puts("");
}
}
MX operator * (const MX &b) const
{
MX c; c.O();
for (int i = 0; i < G; ++i)
{
for (int j = 0; j < G; ++j)
{
for (int k = 0; k < G; ++k)
{
c.v[i][j] = (c.v[i][j] + (UL)v[i][k] * b.v[k][j]) % Z;
}
}
}
return c;
}
MX operator + (const MX &b) const
{
MX c; c.O();
for (int i = 0; i < G; ++i)
{
for (int j = 0; j < G; ++j)
{
c.v[i][j] = (v[i][j] + b.v[i][j]) % Z;
}
}
return c;
}
MX operator ^ (LL p) const
{
MX y; y.E();
MX x; memcpy(x.v, v, sizeof(v));
while (p)
{
if (p & 1)y = y * x;
x = x * x;
p >>= 1;
}
return y;
}
}a, b;
int casenum, casei;
int getpow(int n, int K)
{
a.O(); b.O();
for (int i = 0; i <= K; ++i)a.v[0][i] = 1;
for (int i = 0; i <= K; ++i)b.v[0][i] = 1;
for (int i = 1; i <= K; ++i)
{
for (int j = i; j <= K; ++j)
{
b.v[i][j] = (b.v[i - 1][j - 1] + b.v[i][j - 1]) % Z;
}
}
a = a * (b ^ (n - 1));
return a.v[0][K];
}
int main()
{
scanf("%d", &casenum);
for (casei = 1; casei <= casenum; ++casei)
{
int n, aa, bb;
scanf("%d%d%d", &n, &aa, &bb);
/*
b.v[0] = { 0,2,0,0,0,0,0 };
b.v[1] = { 1,1,0,0,0,0,0 };
b.v[2] = { 0,1,1,1,1,1,1 };
b.v[3] = { 0,4,0,1,2,3,4 };
b.v[4] = { 0,6,0,0,1,3,6 };
b.v[5] = { 0,4,0,0,0,1,4 };
b.v[6] = { 0,1,0,0,0,0,1 };
*/
a.v[0][0] = aa; a.v[0][1] = bb; a.v[0][2] = 1; a.v[0][3] = 2; a.v[0][4] = 4; a.v[0][5] = 8; a.v[0][6] = 16;
b.v[0][0] = 0; b.v[0][1] = 2; b.v[0][2] = 0; b.v[0][3] = 0; b.v[0][4] = 0; b.v[0][5] = 0; b.v[0][6] = 0;
b.v[1][0] = 1; b.v[1][1] = 1; b.v[1][2] = 0; b.v[1][3] = 0; b.v[1][4] = 0; b.v[1][5] = 0; b.v[1][6] = 0;
b.v[2][0] = 0; b.v[2][1] = 1; b.v[2][2] = 1; b.v[2][3] = 1; b.v[2][4] = 1; b.v[2][5] = 1; b.v[2][6] = 1;
b.v[3][0] = 0; b.v[3][1] = 4; b.v[3][2] = 0; b.v[3][3] = 1; b.v[3][4] = 2; b.v[3][5] = 3; b.v[3][6] = 4;
b.v[4][0] = 0; b.v[4][1] = 6; b.v[4][2] = 0; b.v[4][3] = 0; b.v[4][4] = 1; b.v[4][5] = 3; b.v[4][6] = 6;
b.v[5][0] = 0; b.v[5][1] = 4; b.v[5][2] = 0; b.v[5][3] = 0; b.v[5][4] = 0; b.v[5][5] = 1; b.v[5][6] = 4;
b.v[6][0] = 0; b.v[6][1] = 1; b.v[6][2] = 0; b.v[6][3] = 0; b.v[6][4] = 0; b.v[6][5] = 0; b.v[6][6] = 1;
if (n == 1)printf("%d\n", aa);
else
{
a = a * (b ^ (n - 2));
printf("%u\n", a.v[0][1]);
}
}
return 0;
}
/*
【题意】
f[1] = a;
f[2] = b;
f[i] = 2 * f[i - 2] + f[i - 1] + i ^ 4;
求f[n]
【分析】
如果我们需要使用到i ^ k,其只能由 (i - 1) ^ k转移而来。手动化简,得到——
(i)^4 - (i-1)^4 = 4*(i)^3 - 6*(i)^2 + 4*(i)^1 - 1;
(i)^3 - (i-1)^3 = 3*(i)^2 - 3*(i)^1 + 1;
(i)^2 - (i-1)^2 = 2*(i)^1 - 1;
(i)^1 - (i-1)^1 = 1;
a.v[0] = { 0,a,b,2,4,8,16};
b.v[0] = { 0,2,0,0,0,0,0 };
b.v[1] = { 1,1,0,0,0,0,0 };
b.v[2] = { 0,1,1,1,1,1,1 };
b.v[3] = { 0,4,0,1,2,3,4 };
b.v[4] = { 0,6,0,0,1,3,6 };
b.v[5] = { 0,4,0,0,0,1,4 };
b.v[6] = { 0,1,0,0,0,0,1 };
拓展——
如何得到n ^ k 呢? 发现其矩阵的展开类似于二项式展开。getpow(n, K) 就是 n ^ K;
int getpow(int n, int K)
{
a.O(); b.O();
for (int i = 0; i <= K; ++i)a.v[0][i] = 1;
for (int i = 0; i <= K; ++i)b.v[0][i] = 1;
for (int i = 1; i <= K; ++i)
{
for (int j = i; j <= K; ++j)
{
b.v[i][j] = (b.v[i - 1][j - 1] + b.v[i][j - 1]) % Z;
}
}
a = a * (b ^ (n - 1));
return a.v[0][K];
}
【时间复杂度&&优化】
O(7 ^ 3 * log(n))
【数据】
2
3 1 2
4 1 10
*/