矩阵快速幂
https://blog.csdn.net/u012061345/article/details/52224623
讲矩阵快速幂推公式的。
https://blog.csdn.net/zhangxiaoduoduo/article/details/81807338
HDU 4565不会,涉及共轭复数???????
https://baike.baidu.com/item/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97/99145?fr=aladdin
讲斐波那锲数列的
斐波那契数列通项公式。
平方与前后项
与集合子集
奇数项求和
偶数项求和
平方求和
隔项关系
两倍项关系
其他公式
杨辉三角
兔子繁殖问题
经过月数
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
… |
幼仔对数
|
1
|
0
|
1
|
1
|
2
|
3
|
5
|
8
|
13
|
21
|
34
|
55
|
… |
成兔对数
|
0
|
1
|
1
|
2
|
3
|
5
|
8
|
13
|
21
|
34
|
55
|
89
|
|
总体对数
|
1
|
1
|
2
|
3
|
5
|
8
|
13
|
21
|
34
|
55
|
89
|
144
|
poj 3070
题目大意(百度机翻)
在斐波纳契数列的整数序列,F0 = 0,F1 = 1,和Fn = 1 + Fn Fn−2 n≥2。
例如,斐波那契数列的前十项是:0, 1, 1,2, 3, 5,8, 13, 21,34,…
斐波那契数列的另一个公式是
给定一个整数n,你的目标是计算FN的最后4个数字。
输入输入测试文件将包含多个测试用例。
每个测试案例是由单独的一行包含N(0≤N≤1000000000)。
文件结尾是由一个单一的行数−1表示。输出对于每个测试用例,输出FN的最后四个数字。
如果FN的最后四个数字都为零,则输出“0”;
否则,省略任何前导零(即,输出Fn mod 10000)。
#include <cstdio> #include <iostream> using namespace std; const int MOD = 10000; struct matrix { int m[2][2]; }ans, base; matrix multi(matrix a, matrix b) { matrix tmp; for(int i = 0; i < 2; ++i) { for(int j = 0; j < 2; ++j) { tmp.m[i][j] = 0; for(int k = 0; k < 2; ++k) tmp.m[i][j] = (tmp.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD; } } return tmp; } int fast_mod(int n) // 求矩阵 base 的 n 次幂 { base.m[0][0] = base.m[0][1] = base.m[1][0] = 1; base.m[1][1] = 0; ans.m[0][0] = ans.m[1][1] = 1; // ans 初始化为单位矩阵 ans.m[0][1] = ans.m[1][0] = 0; while(n) { if(n & 1) //实现 ans *= t; 其中要先把 ans赋值给 tmp,然后用 ans = tmp * t { ans = multi(ans, base); } base = multi(base, base); n >>= 1; } return ans.m[0][1]; } int main() { int n; while(scanf("%d", &n) && n != -1) { printf("%d\n", fast_mod(n)); } return 0; }
poj 3233
求s=A + A2次方+三次方+k次方
输入 A矩阵与k,求结果
解题思路:
第一种方法:
题意为给定矩阵A(以下代码中用ori表示)。以及k, mod ,求 A+A^2+A^3+......A^k 的和对mod取余。
一開始用循环k次,递推的做法,超时。
。。
看了解题报告,求和的时候要用到二分求和。
所求的和用s(k)表示。
当k为偶数时:
比方 k=6,那么 A+A^2+A^3+A^4+A^5+A^6= A+A^2+A^3+ A^3*(A+A^2+A^3)
s(k)=s(k/2)+A^(n/2) * s(k/2) 即s(k)=(E+A^(n/2))*s(n/2) (E为单位矩阵)
当k为奇数时:
s(k)=s(k-1)+A^k , 那么k-1为偶数。能够依照上面的二分
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; const int maxn=31; int n,k,mod; struct mat { int arr[maxn][maxn]; mat() { memset(arr,0,sizeof(arr)); } }; mat mul(mat a,mat b) { mat ret; for(int i=0;i<n;i++) for(int k=0;k<n;k++) { if(a.arr[i][k]) for(int j=0;j<n;j++) { ret.arr[i][j]+=a.arr[i][k]*b.arr[k][j]; if(ret.arr[i][j]>=mod) ret.arr[i][j]%=mod; } } return ret; } mat add(mat a,mat b) { mat an; for(int i=0;i<n;i++) for(int j=0;j<n;j++) { an.arr[i][j]=a.arr[i][j]+b.arr[i][j]; if(an.arr[i][j]>=mod) an.arr[i][j]%=mod; } return an; } mat power(mat p,int k) { if(k==1) return p; mat e; for(int i=0;i<n;i++) e.arr[i][i]=1; if(k==0) return e; while(k) { if(k&1) e=mul(p,e); p=mul(p,p); k>>=1; } return e; } void output(mat ans) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) { if(j==n-1) cout<<ans.arr[i][j]<<endl; else cout<<ans.arr[i][j]<<" "; } } mat cal(mat ori,int k) { if(k==1) return ori; if(k&1) return add(cal(ori,k-1),power(ori,k));//当k为奇数时,减1变为偶数 S(K)=S(K-1)+ori^K else return mul(add(power(ori,0),power(ori,k>>1)),cal(ori,k>>1)); //当K为偶数时,S(K)=(1+ori^(K/2))*S(K/2) } int main() { while(scanf("%d%d%d",&n,&k,&mod)!=EOF) { mat ori,ans; for(int i=0;i<n;i++) for(int j=0;j<n;j++) { scanf("%d",&ori.arr[i][j]); if(ori.arr[i][j]>=mod) ori.arr[i][j]%=mod; } ans=cal(ori,k); output(ans); } return 0; }
https://blog.csdn.net/qq_36679229/article/details/89253485
https://cn.vjudge.net/contest/299524#problem/A
https://blog.csdn.net/Wen_Yongqi/article/details/83757775
类似于兔子繁衍的题
Apple Trees
题目描述:
这个题目讲述的是,假设存在一棵苹果树,每过十年,这些苹果树上便会长出个苹果,代表苹果树的岁数,这些新长出来的苹果不会停留在树上,每个苹果会掉到地上长出新的苹果树,然后这些苹果树的寿命是45岁,题目让我们求的是第年总共有多少棵苹果树。
题目分析:
根据苹果树的寿命,我们可以求出苹果树在10岁,20岁,30岁,40岁长出来的苹果数分别为16,9,4和1,然后根据这个关系建立递推关系式:,其中代表的是,在第年新长出来苹果树的数目。
由于n最大可达到,因此可以将上述递推关系式用矩阵表示:
注意这里的g值表示是新增的苹果树。
因为苹果树会死,所以g(n)就等于n到n-4或n-5新增的树(4还是5这个题目要根据余数来确定),其他的都已经死了。
然后利用矩阵快速幂就可以快速求出答案。
#include <iostream> #include <cstdio> #include <stdio.h> #include <cstdlib> #include <stdlib.h> #include <cmath> #include <math.h> #include <algorithm> #include <cstring> #include <string> #include <string.h> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #include <bitset> #include <deque> #define reg register #define ll long long #define ull unsigned long long #define INF 0x3f3f3f3f #define mod 1000000007 #define min(a,b) (a<b?a:b) #define max(a,b) (a>b?a:b) #define lowbit(x) (x&(-x)) using namespace std; struct node { ll matrix[5][5]; node () { memset(matrix,0,sizeof(matrix)); } }; node operator * (const node &a,const node &b) { node ans; for (int i=0;i<5;i++) { for (int j=0;j<5;j++) { for (int k=0;k<5;k++) ans.matrix[i][j]=(ans.matrix[i][j]+a.matrix[i][k]*b.matrix[k][j]%mod)%mod; } } return ans; } node m_pow(node m,ll t) { node ans; for (int i=0;i<5;i++) ans.matrix[i][i]=1; while (t) { if (t&1) ans=ans*m; t>>=1; m=m*m; } return ans; } int main() { ll n; cin>>n; node m; m.matrix[0][0]=16; m.matrix[0][1]=9; m.matrix[0][2]=4; m.matrix[0][3]=1; m.matrix[1][0]=m.matrix[2][1]=m.matrix[3][2]=m.matrix[4][3]=1; node ans=m_pow(m,n/10); if (n%10<5) { cout<<(ans.matrix[0][0]+ans.matrix[1][0]+ans.matrix[2][0]+ans.matrix[3][0]+ans.matrix[4][0])%mod; return 0; } cout<<(ans.matrix[0][0]+ans.matrix[1][0]+ans.matrix[2][0]+ans.matrix[3][0])%mod; return 0; }