【矩阵专题】
http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6930
1000:
题意:裸的斐波拉契,裸的不能再裸 n<10^12;
代码:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
#define LL long long
using namespace std;
struct node
{
int mat[2][2];
};
node a={1,1,1,0};
node ret={1,0,0,1};
node NUL={0,0,0,0};
node matmult(node A,node B,int mod)
{
node C=NUL;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
{
C.mat[i][j]=(C.mat[i][j]+A.mat[i][k]*B.mat[k][j])%mod;
}
return C;
}
node quickmatpow(node A,LL n,int mod)
{
node c=ret;
while(n!=0)
{
if(n&1==1) c=matmult(c,A,mod);
n=n>>1;
A=matmult(A,A,mod);
}
return c;
}
LL n;
void init()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
}
int main()
{
// init();
node c;
while(cin>>n&&n!=-1)
{
c=quickmatpow(a,n,10000);
printf("%d\n",c.mat[0][1]);
}
}
1001
题意
A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973。
裸的 没什么好说的
/*
第一次没过样例是因为 写ret 的时候 只给对角线赋值为1 忘记clear了
*/
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
#define LL long long
using namespace std;
void init()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
}
struct node
{
int mat[15][15];
void clear()
{
for(int i=0;i<15;i++)
for(int j=0;j<15;j++)
mat[i][j]=0;
}
void ret()
{
for(int i=0;i<15;i++)
for(int j=0;j<15;j++)
mat[i][j]=0;
for(int i=0;i<15;i++)
mat[i][i]=1;
}
};
node fir;
LL n,k;
node matmult(node a,node b,int mod)
{
node c;
c.clear();
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
return c;
}
node quickmatpow(node a,LL n,int mod)
{
node c;
c.ret();
while(n!=0)
{
if(n&1==1) c=matmult(c,a,mod);
n=n>>1;
a=matmult(a,a,mod);
}
return c;
}
void input()
{
scanf("%I64d%I64d",&n,&k);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&fir.mat[i][j]);
}
void solve()
{
node c;
int ans=0;
c=quickmatpow(fir,k,9973);
for(int i=0;i<n;i++)
{
ans=(ans+c.mat[i][i])%9973;
}
printf("%d\n",ans);
}
int main()
{
// init();
int T;
cin>>T;
while(T--)
{
input();
solve();
}
return 0;
}
1002
题意:
A是一个矩阵 计算S=A+A^2......A^k-1+A^k;
区分奇偶来二分! 看了题解才会做的
本来的想法是涉及到矩阵的逆的
/*
1.WA 不明原因 改成全long long
2.
2 1000000 4
0 1
1 1
99%错误答案:
0 0
0 0
调试原因:不清楚
3.WA 继续调试2
4.发现原因 n为奇数时处理错误
*/
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
#define LL long long
using namespace std;
struct node
{
LL mat[40][40];
void clear()
{
for(int i=0;i<40;i++)
for(int j=0;j<40;j++)
mat[i][j]=0;
}
void ret()
{
clear();
for(int i=0;i<40;i++)
mat[i][i]=1;
}
};
LL n,k,m;
node A;
void init()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
}
void input()
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%I64d",&A.mat[i][j]);
}
node matmult(node a,node b,LL mod)
{
node c;
c.clear();
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
return c;
}
node quickmatpow(node a,LL n,LL mod)
{
node c;
c.ret();
while(n!=0)
{
if(n&1==1) c=matmult(c,a,mod);
n=n>>1;
a=matmult(a,a,mod);
}
return c;
}
node matadd(node a,node b,LL mod)
{
node c;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
c.mat[i][j]=(a.mat[i][j]+b.mat[i][j])%mod;
return c;
}
node getans(int n,int mod)
{
node c,d;
c.clear();
d.clear();
if(n==1) return A;
else
{
c=getans(n/2,mod);
if(n%2==0)
{
d=quickmatpow(A,n/2,mod);
return matadd(c,matmult(d,c,mod),mod);
}
else
{
d=quickmatpow(A,(n/2)+1,mod);
return matadd(d,matadd(c,matmult(d,c,mod),mod),mod);
}
}
}
void solve()
{
node ans;
ans.clear();
ans=getans(k,m);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
printf("%I64d",ans.mat[i][j]);
if(j!=n-1) printf(" ");
}
printf("\n");
}
}
int main()
{
//init();
while(cin>>n>>k>>m)
{
input();
solve();
}
}
1003
题意:
询问长度为N的队伍中 可能为M,或F 问不存在 FFF或FMF的排列总数。
之前做过的一道题
http://blog.csdn.net/zy691357966/article/details/43084647
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
using namespace std;
int L,M;
struct node
{
int mat[5][5];
}a,e,ans;
int mat2[5];
void CSH()
{
mat2[1]=9;
mat2[2]=6;
mat2[3]=4;
mat2[4]=2;
for(int i=1;i<=4;i++)
{
e.mat[i][i]=1;
mat2[i]=mat2[i]%M;
}
memset(a.mat,0,sizeof(a.mat));
a.mat[1][1]=a.mat[1][3]=a.mat[1][4]=1;
a.mat[2][1]=a.mat[3][2]=a.mat[4][3]=1;
}
node MatrixMult(node A,node B,int mod)
{
node p;
memset(p.mat,0,sizeof(p.mat));
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
{
for(int k=1;k<=4;k++)
p.mat[i][j]+=A.mat[i][k]*B.mat[k][j];
p.mat[i][j]=p.mat[i][j]%mod;
}
return p;
}
node kuaisumi(node A,int N,int mod)
{
node di=e;
while(N>0)
{
if(N&1)
{
di=MatrixMult(di,A,mod);
}
A=MatrixMult(A,A,mod);
N=N>>1;
}
return di;
}
void solve()
{
int ANS=0;
for(int i=1;i<=4;i++)
{
ANS+=ans.mat[1][i]*mat2[i];
ANS=ANS%M;
}
printf("%d\n",ANS);
}
int main()
{
while(cin>>L>>M)
{
CSH();
if(L>4)
ans=kuaisumi(a,L-4,M);
if(L>4)
solve();
else
printf("%d\n",mat2[L]);
}
return 0;
}
1004
题目大意:
If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .
齐次递推,很容易由1003 得出公式
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define LL long long
#define oo 0x13131313
using namespace std;
LL k,m;
void init()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
}
struct node
{
LL mat[15][15];
void clear() {memset(mat,0,sizeof(mat));}
void ret() {
clear();
for(int i=0;i<15;i++)
mat[i][i]=1;
}
};
node A;
void input()
{
A.clear();
for(int i=0;i<10;i++)
scanf("%d",&A.mat[0][i]);
for(int i=1;i<10;i++)
A.mat[i][i-1]=1;
}
node matmult(node a,node b,LL mod)
{
node c;c.clear();
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
for(int k=0;k<10;k++)
c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
return c;
}
node quickmatpow(node a,LL n,LL mod)
{
node c;c.ret();
while(n!=0)
{
if(n&1==1) c=matmult(c,a,mod);
n=n>>1;
a=matmult(a,a,mod);
}
return c;
}
void solve()
{
LL ans=0;
node c;c.clear();
c=quickmatpow(A,k-9,m);
for(int i=0;i<10;i++)
ans=(ans+c.mat[0][i]*(9-i))%m;
printf("%I64d\n",ans);
}
int main()
{
// init();
while(cin>>k>>m)
{
input();
solve();
}
return 0;
}
接下来几个题目太强悍了 我必须新写一篇
浙公网安备 33010602011771号