来!接着写题解,立个flag:矩阵快速幂题解不写完今晚不睡觉!
此题解是接着矩阵快速幂1写的,此篇有哪里写不清楚的地方导致看不懂的可以先看1:https://blog.csdn.net/qq_45364953/article/details/99705663
目录
来!接着写题解,立个flag:矩阵快速幂题解不写完今晚不睡觉!
问题四:
Jzzhu and Sequences
Jzzhu has invented a kind of sequences, they meet the following property:
You are given x and y, please calculate fn modulo 1000000007 (109 + 7).
Input
The first line contains two integers x and y (|x|, |y| ≤ 109). The second line contains a single integer n (1 ≤ n ≤ 2·109).
Output
Output a single integer representing fn modulo 1000000007 (109 + 7).
Examples
Input
2 3
3
Output
1
Input
0 -1
2
Output
1000000006
Note
In the first sample, f2 = f1 + f3, 3 = 2 + f3, f3 = 1.
In the second sample, f2 = - 1; - 1 modulo (109 + 7) equals (109 + 6).
题意:给出f1,f2,求fn。
分析:和斐波那契数列一样,把转移矩阵换一下,f1,f2换一下就行。不过此题不用那么复杂可以发现这个数列的fn最后一位是有周期的,多写几个f 就发现了T=6,然后根据周期就可以“投机取巧”(说白了是自己太懒不想学矩阵,我能怎么办自己太菜)的把fn转换成输出f0到f5之间的哪个数了,很明显这个数是n➗6的余数即n%6。
代码:
#include<iostream>
using namespace std;
int main() {
long long int f[6], ans = 0, ans1 = 0, ans2 = 0, n = 0, k = 0,mod=1000000007;
cin >> ans1 >> ans2;
cin >> n;
f[1] = ans1 % mod;
f[2] = ans2 % mod;
f[3] = (ans2 - ans1 )% mod;
f[4] = (f[3] - ans2 )% mod;
f[5] = (f[4] - f[3] )% mod;
f[0] = (f[5] - f[4] )% mod;
cout << (f[n % 6] + mod) % mod; //+mod很重要
return 0;
}
正经做法呢?代码:
#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
struct matrix
{
ll mat[2][2];
matrix() {
memset(mat, 0, sizeof(mat));
}
}U, F;
ll mod;
matrix mul(matrix Q, matrix A)
{
matrix C;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
C.mat[i][j] = (C.mat[i][j] + A.mat[i][k] * Q.mat[k][j]%mod)%mod;
return C;
}
matrix powmul(matrix A, ll m)
{
matrix ans = F;
while (m > 0)
{
if (m & 1)
ans = mul(ans, A);
A = mul(A, A);
m >>= 1;
}
return ans;
}
int main() {
mod = 1000000007;
ll a, b, n;
cin >> a >> b;
cin >> n;
if (n == 1)
cout << a << endl;
else {
U.mat[0][0] = 1; U.mat[0][1] = -1;
U.mat[1][0] = 1; U.mat[1][1] = 0;
F.mat[0][0] = b; F.mat[0][1] = 0;
F.mat[1][0] = a; F.mat[1][1] = 0;
matrix ans = powmul(U, n-1);
cout << (ans.mat[1][0]+mod) %mod<< endl;
}
return 0;
}
问题五:
Recurrences
Consider recurrent functions of the following form:
f(n) = a1f(n−1) + a2f(n−2) + a3f(n−3) + ... + adf(n−d), for n > d,
where a1, a2, ..., ad are arbitrary constants.
A famous example is the Fibonacci sequence, defined as: f(1) = 1, f(2) = 1, f(n) = f(n−1) +f (n−2). Here d = 2, a1 = 1, a2 = 1. Every such function is completely described by specifying d (which is called the order of recurrence), values of d coefficients: a1, a2, ..., ad, and values of f(1), f(2), ..., f(d). You’ll be given these numbers, and two integers n and m. Your program’s job is to compute f(n) modulo m.
Input
Input file contains several test cases. Each test case begins with three integers: d, n, m, followed by two sets of d non-negative integers. The first set contains coefficients: a1, a2, ..., ad. The second set gives values of f(1), f(2), ..., f(d). You can assume that: 1 ≤ d ≤ 15, 1 ≤ n ≤ 231 −1, 1 ≤ m ≤ 46340. All numbers in the input will fit in signed 32-bit integer. Input is terminated by line containing three zeroes instead of d, n, m. Two consecutive test cases are separated by a blank line.
Output
For each test case, print the value of f(n)( mod m) on a separate line. It must be a non-negative integer, less than m.
Sample Input
1 1 100 //d n m
2 //系数a1
1 //fn的值
//这里有一个空行
2 10 100
1 1
1 1
3 2147483647 12345
12345678 0 12345
1 2 3
0 0 0
Sample Output
1
55
423
题意:给出了递推式告诉你f(1),f(2),,,到f(d)的值以及递推式每项的系数求f(n)
和斐波那契数列差不多吧,变复杂了,增加了递推式的系数和项数,细节要好好注意。
举例,d=5的矩阵关系式为:
|a1 a2 a3 a4 a5| | f[n] | | f[n+1]|
|1 0 0 0 0 | | f[n-1] | | f[n] |
|0 1 0 0 0 | * | f[n-2] | = | f[n-1] |
|0 0 1 0 0 | | f[n-3] | | f[n-2] |
|0 0 0 1 0 | | f[n-4] | | f[n-3] |
代码:
#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
struct matrix
{
ll mat[15][15];
matrix() {
memset(mat, 0, sizeof(mat));
}
}U, F;
ll mod;
int d;
matrix mul(matrix Q, matrix A)
{
matrix C;
for (int i = 0; i < d; i++)
for (int j = 0; j < d; j++)
for (int k = 0; k < d; k++)
C.mat[i][j] = (C.mat[i][j] + (A.mat[i][k] * Q.mat[k][j]) % mod) % mod;
return C;
}
matrix powmul(matrix A, int m)
{
matrix ans = F;
while (m > 0)
{
if (m & 1)
ans = mul(ans, A);
A = mul(A, A);
m >>= 1;
}
return ans;
}
int main() {
ll n;
while (cin >> d >> n >> mod)
{
if (d == 0 && n == 0 && mod == 0)
break;
for (int i = 0; i < d; i++)
cin >> U.mat[0][i]; //转移矩阵的第一行是递推式系数a1,a2,a3...
for (int i = 1, j = 0; i < d; i++, j++)
U.mat[i][j] = 1; //对角线向下平移一格全是1,其他为零
for (int i = d - 1; i >= 0; i--)
cin >> F.mat[i][0]; //倒着输入,f1在最下面
if (n <=d)
cout << F.mat[d - n][0]%mod<<endl;
else {
if (d == 1) {
matrix ans0 = powmul(U, n - 1);
cout << ans0.mat[0][0] << endl;
}
else {
matrix ans = powmul(U, n - d + 1);
//注意这里为什么是n-d+1,矩阵最开始有了fd,再乘转移矩阵得到的fn肯定是fd,fd+1...之类的。
//乘n-d次方得到的是f(d+n-d)=fn,在ans.mat[0][0]里面;乘n-d+1次方fn就在ans.mat[1][0]里面
cout << ans.mat[1][0] << endl;
}
}
getchar();
}
return 0;
}
总结:细节决定成败啊!无论什么时候输出总要模上mod,转移矩阵究竟要乘多少次?转移方程怎么写?
问题六:
Contemplation! Algebra
Given the value of a+b and ab you will have to find the value of an + bn
Input
The input file contains several lines of inputs. Each line except the last line contains 3 non-negative integers p, q and n. Here p denotes the value of a+b and q denotes the value of ab. Input is terminated by a line containing only two zeroes. This line should not be processed. Each number in the input file fits in a signed 32-bit integer. There will be no such input so that you have to find the value of 00.
Output
For each line of input except the last one produce one line of output. This line contains the value of an + bn. You can always assume that an + bn fits in a signed 64-bit integer.
Sample Input
10 16 2
7 12 3
0 0
Sample Output
68
91
题意: 告诉a+b,ab的值,给一个n,求
分析:写出矩阵:
#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
struct matrix
{
ll mat[2][2];
matrix() {
memset(mat, 0, sizeof(mat));
}
}U, F;
ll mod;
matrix mul(matrix Q, matrix A)
{
matrix C;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
C.mat[i][j] = (C.mat[i][j] + (A.mat[i][k] * Q.mat[k][j])%mod)%mod;
return C;
}
matrix powmul(matrix A, ll m)
{
matrix ans = F;
while (m > 0)
{
if (m & 1)
ans = mul(ans, A);
A = mul(A, A);
m >>= 1;
}
return ans;
}
int main() {
mod = 1000000007;
ll a, b, n;
cin >> a >> b;
cin >> n;
if (n == 1)
cout << (a+mod)%mod << endl;
else {
U.mat[0][0] = 1; U.mat[0][1] = -1;
U.mat[1][0] = 1; U.mat[1][1] = 0;
F.mat[0][0] = b; F.mat[0][1] = 0;
F.mat[1][0] = a; F.mat[1][1] = 0;
matrix ans = powmul(U, n-1);
cout << (ans.mat[1][0]+mod) %mod;
}
return 0;
}
问题七:
Reading comprehension
Read the program below carefully then answer the question.
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include<iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include<vector>
const int MAX=100000*2;
const int INF=1e9;
int main()
{
int n,m,ans,i;
while(scanf("%d%d",&n,&m)!=EOF)
{
ans=0;
for(i=1;i<=n;i++)
{
if(i&1)ans=(ans*2+1)%m;
else ans=ans*2%m;
}
printf("%d\n",ans);
}
return 0;
}
Input
Multi test cases,each line will contain two integers n and m. Process to end of file.
[Technical Specification]
1<=n, m <= 1000000000
Output
For each case,output an integer,represents the output of above program.
Sample Input
1 10
3 100
Sample Output
1
5
题意:根据题中代码求ans,但是不能直接用题目中的代码提交,当n很大的时候会超时,我们需要用快速幂优化。
分析:以2为一组,n=2时为ans(1),n=4时为ans(2),n=6时为ans(3),
则n为偶数时:n=n/2 ,ans(n)=4×ans(n-1)+2
n为奇数时:n先减1,n=n/2,求出ans(n)=4×ans(n-1)+2,先开始的时候n减了1,现在多算一步所以结果还要×2+1
矩阵:
代码:
#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
struct matrix
{
ll mat[2][2];
matrix() {
memset(mat, 0, sizeof(mat));
}
}U, F;
ll mod;
matrix mul(matrix Q, matrix A)
{
matrix C;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
C.mat[i][j] = (C.mat[i][j] + (A.mat[i][k] * Q.mat[k][j]) % mod) % mod;
return C;
}
matrix powmul(matrix A, ll m)
{
matrix ans = F;
while (m > 0)
{
if (m & 1)
ans = mul(ans, A);
A = mul(A, A);
m >>= 1;
}
return ans;
}
int main() {
ll n;
while (cin >> n >> mod)
{
U.mat[0][0] = 4;
U.mat[0][1] = 1;
U.mat[1][0] = 0;
U.mat[1][1] = 1;
F.mat[0][0] = 2;
F.mat[0][1] = 0;
F.mat[1][0] = 2;
F.mat[1][1] = 0;
if (n == 1)
cout << 1 % mod << endl;
else if (n == 2)
cout << 2 % mod << endl;
else if (n == 3)
cout << 5 % mod << endl;
else
{
matrix ans;
if (n % 2 == 0)
{
n >>= 1;
ans = powmul(U, n-1);
cout << ans.mat[0][0] %mod << endl;
}
else
{
n--;
n >>= 1;
ans = powmul(U, n-1);
cout << (ans.mat[0][0]*2+1) % mod << endl;
}
}
}
//system("pause");
return 0;
}
继续矩阵快速幂3:https://blog.csdn.net/qq_45364953/article/details/99771344