等整理完网络流的题目,再整理矩阵的,此坑待填
====================
poj3233 Matrix Power Series
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define FD "%d"
#define FLL "%lld"
int matsz,mod;
const int N=70;
struct matrix
{
int mat[N][N];
matrix(int v)
{
memset(mat,0,sizeof(mat));
for(int i=0;i<matsz;i++)
mat[i][i]=v;
}
matrix operator *(matrix b)
{
matrix tmp(0);
for(int i=0;i<matsz;i++)
for(int k=0;k<matsz;k++)
if(mat[i][k])
{
for(int j=0;j<matsz;j++)
{
tmp.mat[i][j]+=mat[i][k]*b.mat[k][j];
tmp.mat[i][j]%=mod;
}
}
return tmp;
}
void print()
{
for(int i=0;i<matsz;i++)
for(int j=0;j<matsz;j++)
printf(j==matsz-1?"%d\n":"%d ",mat[i][j]);
}
};
matrix qpow(matrix t,int k)
{
matrix ret(1);
while(k)
{
if(k&1)
ret=ret*t;
t=t*t;
k>>=1;
}
return ret;
}
int main()
{
int n,k,m;
while(~scanf("%d%d%d",&n,&k,&m))
{
matsz=n<<1;
mod=m;
matrix t(0);
for(int i=0;i<n;i++)
t.mat[i][i]=t.mat[i][i+n]=1;
for(int i=n;i<matsz;i++)
for(int j=n;j<matsz;j++)
scanf("%d",&t.mat[i][j]);
matrix ret=qpow(t,k+1);
int ans;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
t.mat[i][j]=t.mat[i+n][j+n];
for(int i=n;i<matsz;i++)
for(int j=0;j<n;j++)
t.mat[i][j]=t.mat[i][j+n]*t.mat[i][j+n]%mod;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(i==j)ret.mat[i][j+n] = (ret.mat[i][j+n]-1+mod)%mod;
printf(j==n-1?"%d\n":"%d ",ret.mat[i][j+n]);
}
}
return 0;
}
loj1006 Hex-a-bonacci
题意:
给出递推公式,求第n项。
做法:
构造矩阵,然后快速幂。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int Mod=10000007;
int a, b, c, d, e, f;
int fn( int n ) {
if( n == 0 ) return a;
if( n == 1 ) return b;
if( n == 2 ) return c;
if( n == 3 ) return d;
if( n == 4 ) return e;
if( n == 5 ) return f;
return( fn(n-1) + fn(n-2) + fn(n-3) + fn(n-4) + fn(n-5) + fn(n-6) );
}
const int N=6;
struct matrix
{
long long mat[N][N];
matrix(){memset(mat,0,sizeof(mat));for(int i=0;i<N;i++)mat[0][i]=1;for(int i=1;i<N;i++)mat[i][i-1]=1;}
matrix(int n){memset(mat,0,sizeof(mat));for(int i=0;i<N;i++)mat[i][i]=1;}
void print(){for(int i=0;i<N;i++){for(int j=0;j<N;j++)cout<<mat[i][j]<<" ";printf("\n"); } }
matrix operator *(matrix a)
{
matrix ret;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
{
ret.mat[i][j]=0;
for(int k=0;k<N;k++)
ret.mat[i][j]+=mat[i][k]*a.mat[k][j];
ret.mat[i][j]%=Mod;
}
return ret;
}
};
int solve(int n)
{
int ret=0;
matrix a,t(n);
n-=5;
while(n)
{
if(n&1)
t=t*a;
a=a*a;
n>>=1;
}
for(int i=0;i<N;i++)
ret=(ret+t.mat[0][i]*fn(5-i))%Mod;
return ret;
}
int main() {
// freopen("in","r",stdin);
int n, caseno = 0, cases,ret;
scanf("%d", &cases);
while( cases-- ) {
scanf("%d %d %d %d %d %d %d", &a, &b, &c, &d, &e, &f, &n);
if(n<=5)
ret=fn(n);
else
ret=solve(n);
printf("Case %d: %d\n", ++caseno,ret % 10000007);
}
return 0;
}
hdu4686 Arc of Dream(2013多校题目)
题意:
给出递推公式,求第n项。
做法:
构造矩阵,然后快速幂。
反思:
注意及时取模,赋值不要写错了。
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
#define FLL "%I64d"
const LL Mod=1e9+7;
const int Maxn=7;
struct martix
{
LL mat[Maxn][Maxn];
martix()
{
memset(mat,0,sizeof(mat));
}
martix(int a)
{
memset(mat,0,sizeof(mat));
for(int i=0; i<Maxn; i++)mat[i][i]=1;
}
void operator *=(const martix &a)
{
martix tmp;
for(int i=0; i<Maxn; i++)
for(int k=0; k<Maxn; k++)
if(mat[i][k])
for(int j=0; j<Maxn; j++)
{
tmp.mat[i][j]+=(mat[i][k]*a.mat[k][j])%Mod;
tmp.mat[i][j]%=Mod;
}
for(int i=0; i<Maxn; i++)
for(int j=0; j<Maxn; j++)
mat[i][j]=tmp.mat[i][j];
}
};
martix qpow(martix a,LL n)
{
martix ret(1);
while(n)
{
if(n&1)
ret*=a;
a*=a;
n>>=1;
}
return ret;
}
int main()
{
LL n,a0,ax,ay,b0,bx,by,s1;
while(~scanf(FLL,&n))
{
scanf(FLL FLL FLL FLL FLL FLL,&a0,&ax,&ay,&b0,&bx,&by);
if(!n)
{
puts("0");
continue;
}
s1=a0*b0%Mod;
if(n==1)
{
printf(FLL,s1);
puts("");
continue;
}
martix ret;
ret.mat[0][0]=ret.mat[0][1]=1;
ret.mat[1][1]=ax*bx%Mod;
ret.mat[1][2]=ax*by%Mod;
ret.mat[1][3]=ay*bx%Mod;
ret.mat[1][4]=1;
ret.mat[2][2]=ax;
ret.mat[2][5]=1;//!!!
ret.mat[3][3]=bx;
ret.mat[3][6]=ret.mat[4][4]=ret.mat[5][5]=ret.mat[6][6]=1;
ret=qpow(ret,n-1);
LL ans=0,a1,b1;
a1=(a0%Mod*ax%Mod+ay)%Mod;
b1=(b0%Mod*bx%Mod+by)%Mod;
LL tmp[Maxn]={s1,a1*b1%Mod,a1,b1,ay*by%Mod,ay,by};
for(int i=0;i<Maxn;i++)
{
ans+=(tmp[i]*ret.mat[0][i])%Mod;
ans%=Mod;
}
printf(FLL,ans);
puts("");
}
return 0;
}
poj3735 Training little cats
题意:
给出n个数,一开始都是0。
有三种操作:g i:第i个数加一;e i:第i个数变成0;s i j:第i和第j个数交换。
每次给你k个操作,然后重复这k个操作m次,求最后n个数分别是多少。
做法:
把三种操作用矩阵乘法来表示
反思:
没用long long wa了一次。
#include <cstdio>
#include <cstring>
using namespace std;
#define SET(a,x) memset(a,x,sizeof(a))
#define RE(i,n) for(long long i = 1; i <= n; i++)
#define _RE(i,n) for(long long i = 0; i <= n; i++)
long long n,m,k;
const long long MAX = 110;
struct martix {
long long mat[MAX][MAX];
long long a,b;
martix(long long f=0) {
SET(mat,0);
_RE(i,n)mat[i][i]=f;
}
void operator *= (martix t) {
martix ret;
_RE(i,n)
_RE(k,n)if(mat[i][k])
_RE(j,n) {
ret.mat[i][j] += mat[i][k] * t.mat[k][j];
// ret.mat[i][j] %= MOD;
}
_RE(i,n)
_RE(j,n)
mat[i][j] = ret.mat[i][j];
}
void dis(){
_RE(i,n){
_RE(j,n)
printf("%I64d ",mat[i][j]);
puts("");
}
}
};
martix qpow(martix ret,long long m){
martix ans(1);
while(m){
if(m & 1)
ans *= ret;
ret *= ret;
m >>= 1;
}
return ans;
}
int main() {
while(scanf("%I64d%I64d%I64d",&n,&m,&k),n||m||k) {
char op[5];
long long x,y;
martix ret(1);
while(k--) {
scanf("%s%I64d",op,&x);
martix cur(1);
if(op[0] == 'g') {
cur.mat[x][0] = 1;
} else if(op[0] == 'e') {
cur.mat[x][x] = 0;
} else if(op[0] == 's') {
scanf("%I64d",&y);
cur.mat[x][x] = cur.mat[y][y] = 0;
cur.mat[x][y] = cur.mat[y][x] = 1;
}
cur *= ret;
ret = cur;
}
if(m == 0){
RE(i,n)
printf(i == n?"0\n":"0 ");
continue;
}
ret = qpow(ret,m);
RE(i,n) {
printf(i == n?"%I64d\n":"%I64d ",ret.mat[i][0]);
}
}
}