一些矩阵的定义及运算
结构体定义
struct Mat{
int m[maxn][maxn];
};
Mat matadd(Mat a,Mat b) //两矩阵相加;
{
int i,j;
Mat c;
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
c.m[i][j]=(a.m[i][j]+b.m[i][j])%m;
}
}
return c;
}
乘法
Mat matmul(Mat a,Mat b) //两矩阵相乘;
{
Mat c;
int i,j,k;
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
c.m[i][j]=0;
for(k=0;k<2;k++)
{
c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%m;
}
}
}
return c;
}
Mat qmod(Mat a,int k) //快速幂求a^k;
{
Mat res;
memset(res.m,0,sizeof(res.m));
int i;
for(i=0;i<2;i++) res.m[i][i]=1;
while(k)
{
if(k&1) res=matmul(res,a);
a=matmul(a,a);
k/=2;
}
return res;
}
分治求 a^1+a^2+....+a^n
Mat cal(Mat a,int n) //分治求a^0+a^1+....+a^n
{
if(n==0) return qmod(a,0);
int d=(1+n)/2;
Mat o=cal(a,d-1);
Mat res=matadd(o,matmul(o,qmod(a,d)));
if(n%2==0) res=matadd(res,qmod(a,n));
return res;
}
Mat cal(Mat a,int n) //分治求a^1+a^2+....+a^n
{
if(n==1) return a;
int d=n/2;
Mat o=cal(a,d);
Mat res=matadd(o,matmul(o,qmod(a,d)));
if(n%2==1) res=matadd(res,qmod(a,n));
return res;
}
矩阵求递推
首先,需要有一个递推公式(有些需要自己找规律),然后根据公式或原理自己构造一个矩阵,最后快速幂。
一般这种题目都是看起来简单,但是会无限TLE,就可以联想到快速幂,然后就想到可以用矩阵。
我觉得构造的时候主要就是看每一列和初始值分别相乘后相加得到的值是不是下一个状态的值。每一行代表了每一个值的运算;
一些题目
hdu 1575 直接快速幂;
hdu 3117 比较综合的题目,快速幂求后四项,log+通项公式求前四项
hdu 1757 已知递推公式构造矩阵求快速幂;
poj 3233 求a^0+a^1+……+a^n,分而治之,还有别的方法;
注意:mod尽量要少,可能会导致超时;
hdu 1588 通过已知公式推出a^0+a^1+……+a^n;
注意:有一些特例要单独考虑,边界要弄清楚,还有范围;
hdu 2254 用到了离散数学,我就不想多说什么了,表示一知半解,到现在还不知道为什么答案会有负数.....
hdu 2276 个人觉得这道题很经典,构造的函数不难,但需要找规律;