之前遇到矩阵的一直没看 有时间了 学习学习。。。
(1)快速幂 原理不再赘述 来个模版:
int n;//矩阵的大小
const int mod=9973;
struct matrix
{
int a[10][10];
};
matrix ori,res;
void init()
{
memset(res.a,0,sizeof(res.a));
for(int i=0;i<n;i++)
res.a[i][i]=1;
}//给res初始化为单位矩阵
matrix multiply(matrix x,matrix y)
{
matrix temp;
memset(temp.a,0,sizeof(temp.a));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
for(int k=0;k<n;k++)
{
temp.a[i][j]+=(x.a[i][k]*y.a[k][j]);
temp.a[i][j]%=mod;
}
}
}
return temp;
}
void calc(int num)
{
while(num)
{
if(num&1)
res=multiply(ori,res);
num>>=1;
ori=multiply(ori,ori);
}//最终的结果保存在res 中
// for(int i=0;i<n;i++)
// {
// for(int j=0;j<n;j++)
// cout<<res.a[i][j]<<"\t";
// cout<<endl;
// }
}
hdu 1575 Tr A
题目大意就是求所给矩阵的k次方后得到一个矩阵 然后求所得矩阵主对角线上数字之和
模版题 直接套用模版即可
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n;//矩阵的大小
const int mod=9973;
struct matrix
{
int a[10][10];
};
matrix ori,res;
void init()
{
memset(res.a,0,sizeof(res.a));
for(int i=0;i<n;i++)
res.a[i][i]=1;
}
matrix multiply(matrix x,matrix y)
{
matrix temp;
memset(temp.a,0,sizeof(temp.a));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
for(int k=0;k<n;k++)
{
temp.a[i][j]+=(x.a[i][k]*y.a[k][j]);
temp.a[i][j]%=mod;
}
}
}
return temp;
}
void calc(int num)
{
while(num)
{
if(num&1)
res=multiply(ori,res);
num>>=1;//num的值要变化
ori=multiply(ori,ori);
}
// for(int i=0;i<n;i++)
// {
// for(int j=0;j<n;j++)
// cout<<res.a[i][j]<<"\t";
// cout<<endl;
// }
}
int main()
{
freopen("ceshi.txt","r",stdin);
int tc;
scanf("%d",&tc);
while(tc--)
{
int k;
scanf("%d%d",&n,&k);
init();
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
scanf("%d",&ori.a[i][j]);
}
}
calc(k);
int sum=0;
for(int i=0;i<n;i++)
{
sum=sum+res.a[i][i];
// sum%=mod;
}
// while(sum<0)
// sum+=mod;
printf("%d\n",sum%mod);
}
return 0;
}
hdu 1757 A Simple Math Problem
求一个递推的函数f(k)的值 k<2*10^9 k的值可能会比较大 不能直接求 函数中涉及到的值比较多
f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10)
构造的矩阵是:
|0
|0
|................1|
|a9
我一开始做的时候 矩阵构造错了 最后一行写的是a0-a9
读题要仔细啊骚年!!!
最后将矩阵相乘得到的值的最后一行以此与f0-f9相乘然后相加求和
代码相对来说就比较简单了 代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int m;
struct matrix
{
int a[10][10];
};
matrix ori,res;
void init()
{
memset(res.a,0,sizeof(res.a));
for(int i=0;i<10;i++)
res.a[i][i]=1;
}
matrix multiply(matrix x,matrix y)
{
matrix temp;
memset(temp.a,0,sizeof(temp.a));
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
for(int k=0;k<10;k++)
{
temp.a[i][j]+=x.a[i][k]*y.a[k][j];
temp.a[i][j]%=m;
}
return temp;
}
void calc(int n)
{
while(n)
{
if(n&1)
res=multiply(ori,res);
n>>=1;
ori=multiply(ori,ori);
}
}
int main()
{
//freopen("ceshi.txt","r",stdin);
int k;
while(scanf("%d%d",&k,&m)!=EOF)
{
memset(ori.a,0,sizeof(ori.a));
for(int i=0;i<10;i++)
scanf("%d",&ori.a[9][9-i]);
if(k<10)
printf("%d\n",k%m);
else
{
init();
for(int i=0;i<9;i++)
{
ori.a[i][i+1]=1;
}
int b[10];
for(int i=0;i<10;i++)
b[i]=i;
calc(k-9);
int sum=0;
for(int i=0;i<10;i++)
{
sum+=res.a[9][i]*b[i];
sum%=m;
}
printf("%d\n",sum%m);
}
}
return 0;
}
hdu 2256 Problem of Precision
题目大意就是求一个表达式的2n次方后整数部分模1024的值 与之前在MSDN上末三位整数是一样的
就是表达式一个精度的计算
主要是要推出那个表达式
(sqrt(2)+sqrt(3))^2n=(5+2*sqrt(6))^n=An+sqrt(6)*Bn
(5+2*sqrt(6))^(n+1)=An+1+sqrt(6)*Bn+1=(An+sqrt(6)*Bn)*(5+2*sqrt(6))
所以 An+1=5An+12Bn Bn+1=2*An+5*Bn 从而就可以构造矩阵了
但是光是这样 还不能正确求得解
看的别人的。。
简直了。。。
贴个代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int mod=1024;
struct matrix
{
int a[2][2];
};
matrix ori,res;
void init()
{
res.a[0][1]=res.a[1][0]=0;
res.a[0][0]=res.a[1][1]=1;
}
matrix multiply(matrix x,matrix y)
{
matrix temp;
memset(temp.a,0,sizeof(temp.a));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
{
temp.a[i][j]+=x.a[i][k]*y.a[k][j];
temp.a[i][j]%=mod;
}
return temp;
}
void calc(int n)
{
while(n)
{
if(n&1) res=multiply(ori,res);
n>>=1;
ori=multiply(ori,ori);
}
}
int main()
{
freopen("ceshi.txt","r",stdin);
int tc;
scanf("%d",&tc);
while(tc--)
{
init();
int a1=5,b1=2;
ori.a[0][0]=ori.a[1][1]=5;
ori.a[0][1]=12;
ori.a[1][0]=2;
int n;
scanf("%d",&n);
calc(n-1);
int a2,b2;
//for(int i=0;i<2;i++)
//{
// for(int j=0;j<2;j++)
// {
// printf("%d\t",res.a[i][j]);
// }
// puts("");
//}
a2=res.a[0][0]*a1%mod+res.a[0][1]*b1%mod;
b2=res.a[1][0]*a1%mod+res.a[1][1]*b1%mod;
a2%=mod;
b2%=mod;
//cout<<a2<<" "<<b2<<endl;
// int sum=(int)(a2+sqrt(6)*b2);
int sum=2*a2-1;
printf("%d\n",sum%mod);
}
return 0;
}
//待续 欢迎大家评论 给点建议