这个是乘法加剪枝的。
Mat operator * (Mat a, Mat b) {
Mat c;
memset(c.mat, 0, sizeof(c.mat));
int i, j, k;
for(k = 0; k < n; ++k) {
for(i = 0; i < n; ++i) {
if(a.mat[i][k] <= 0) continue; //不要小看这里的剪枝,cpu运算乘法的效率并不是想像的那么理想(加法的运算效率高于乘法,比如Strassen矩阵乘法)
for(j = 0; j < n; ++j) {
if(b.mat[k][j] <= 0) continue; //剪枝
c.mat[i][j] += a.mat[i][k] * b.mat[k][j];
}
}
}
return c;
}
******************************
这个是自己刚刚改的剪枝,,,,快了30ms,,,
赶脚差不多啦。可能自己写的用得顺手。
用的时候记得改“16”。
struct node mul(node x,node y)
{
int i,j,k;
node z;
memset(z.a,0,sizeof(z.a));
for(i=0;i<16;i++)
{
for(j=0;j<16;j++)
{
for(k=0;k<16;k++)
if(!x.a[i][k]||!y.a[k][j]) continue;
else z.a[i][j]+=x.a[i][k]*y.a[k][j]%m;
z.a[i][j]%=m;
}
}
return z;
}
然后这个是连乘的。
Mat operator ^ (Mat a, int k) {
Mat c;
int i, j;
for(i = 0; i < n; ++i)
for(j = 0; j < n; ++j)
c.mat[i][j] = (i == j); //初始化为单位矩阵
for(; k; k >>= 1) {
if(k&1) c = c*a;
a = a*a;
}
return c;
}
***************************
警觉没有快速幂的模板(自己用过的),赶紧来一发。
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;
int N;
struct matrix
{
int a[3][3];
}origin,res;
matrix multiply(matrix x,matrix y)
{
matrix temp;
memset(temp.a,0,sizeof(temp.a));
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<3;k++)
{
temp.a[i][j]+=x.a[i][k]*y.a[k][j];
}
}
}
return temp;
}
void init()
{
printf("随机数组如下:\n");
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
origin.a[i][j]=rand()%10;
printf("%8d",origin.a[i][j]);
}
printf("\n");
}
printf("\n");
memset(res.a,0,sizeof(res.a));
res.a[0][0]=res.a[1][1]=res.a[2][2]=1; //将res.a初始化为单位矩阵
}
void calc(int n)
{
while(n)
{
if(n&1)
res=multiply(res,origin);
n>>=1;
origin=multiply(origin,origin);
}
printf("%d次幂结果如下:\n",n);
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
printf("%8d",res.a[i][j]);
printf("\n");
}
printf("\n");
}
int main()
{
while(cin>>N)
{
init();
calc(N);
}
return 0;
}
嗯,,,其实快速幂的精髓就是这个,然后我不会运算符重载= =,所以这里每次的乘法要用函数代替啦,其他一样一样。
while(N)
{
if(N&1)
res=res*A;
n>>=1;
A=A*A;
}