8.9上课感悟
2017-08-09 21:03
225 查看
数论课
今天讲数论诶……表示今天数学讲课的课件还是没有要到……(下次我自己拷吧)
话说今天数学讲的真心快,看看OB那边讲得多慢(我们这边放了那边才讲到线性筛)
那些什么线性求逆元之类的东西还是要自己慢慢复习的,感觉听一次忘一次
数论这些东西没什么感悟,主要是自己达到那个数学的理论水平就可以理解了
话说本来正常14:30下课回家……
矩阵
今天最重要的我个人认为是矩阵吧废话不多说,直接切重点
矩阵的加减法没什么好说的吧
主要是乘法运用的比较多
这个公式可能比较抽象,不好理解
那么我们换个东西,变成矩阵的
那么这样矩阵乘法怎么做的就十分明显了
两个矩阵X(A*B),Y(B*C)相乘,大小为(A,C)
矩阵乘法必须满足X的列数=Y的行数
我们在做矩阵的时候,可以把这个矩阵抽象成一个数
显然,矩阵乘法满足结合律和交换律
通过这个性质,我们可以来做矩阵上的dp(后话)
我们来个例题吧
斐波那契数列为 f
=f[n-1]+f[n-2]
求出 f
%p的值 (N<=10^18)
暴力显然T到飞起……
我们可以构造矩阵
这显然满足矩阵乘法的性质
那么f
就能通过矩阵乘法得到
所以最终我们可以得到
然后矩阵快速幂即可
快速幂中途很可能会爆long long,所以建议慢速乘
注:矩阵快速幂和普通的数快速幂一样
来发个代码(不高兴慢速乘了)
struct matrix{ int n,m; LL a[3][3]; matrix(int x,int y,LL A,LL B,LL C,LL D){ n=x,m=y; a[1][1]=A,a[1][2]=B; a[2][1]=C,a[2][2]=D; } }; matrix operator * (matrix x,matrix y){ int N=x.n,M=y.m; matrix ret(N,M,0,0,0,0); for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) for(int k=1;k<=x.m;k++) ret.a[i][j]=(ret.a[i][j]+x.a[i][k]*y.a[k][j])%p; return ret; } matrix Pow(matrix x,LL y){ matrix ret=x,s=x; while(y){ if(y&1) ret=ret*s; s=s*s; y>>=1; } return ret; } LL calc(int n){ matrix tmp(2,2,1,1,1,0),mat(2,2,1,0,1,0); matrix ret=Pow(tmp,n-2)*mat; return ret.a[1][1]%p; }
感觉蛮简单的,自己手动推推应该就能推出来
原来用jyg大神的算法跑10^18肯定T飞,但是一用矩阵速度是飞上去的
对于10^18的数据,矩阵轻松秒出,估计只要50-60ms
这速度简直是飞一般的感觉……
总结
我只总结矩阵这方面的东西一般是用矩阵来优化递推式,第一步当然是求出递推式啦
完了之后建议先将后面的两个要求的矩阵先写出来,然后最前面的常数矩阵可以自己推
什么时候可以用矩阵优化呢?
一般是某个东西比较小,而且我们只要知道那一部分的东西就行了
所以这样矩阵的大小不会太大,时间也不会T
反正今天就是矩阵的入门,后面慢慢学,慢慢理解