转载声明:http://www.cnblogs.com/kuangbin/archive/2012/08/17/2643347.html
(没找到原址,转了kuangbin巨巨的保留而用)
个人感想:最近在敲10道经典矩阵题目,我搞了前9道,最后一道看似看懂了,但也没搞出来,贴下一战绩吧,感觉很有用处.
poj3233
/* Author:GavinjouElephant
* Title:
* Number:
* main meanning:
*
*
*
*/
#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
int Scan()//读入整数外挂.
{
int res = 0, ch, flag = 0;
if((ch = getchar()) == '-') //判断正负
flag = 1;
else if(ch >= '0' && ch <= '9') //得到完整的数
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9' )
res = res * 10 + ch - '0';
return flag ? -res : res;
}
void Out(int a) //输出外挂
{
if(a>9)
Out(a/10);
putchar(a%10+'0');
}
ll N,m,k;
struct mat
{
ll g[35][35];
void Clear()
{
memset(g,0,sizeof(g));
}
};
mat mul(mat A,mat B)
{
mat C;
C.Clear();
for(int i=0;i<N;i++)
{
for(int k=0;k<N;k++)
{
for(int j=0;j<N;j++)
{
C.g[i][j]=(C.g[i][j]+A.g[i][k]*B.g[k][j])%m;
}
}
}
return C;
}
mat cal(mat A,mat B)
{
mat C;
C.Clear();
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
C.g[i][j]=(A.g[i][j]+B.g[i][j])%m;
}
}
return C;
}
mat pow(mat A,ll n)
{
mat B;
B.Clear();
for(int i=0;i<N;i++)
{
B.g[i][i]=1;
}
while(n>0)
{
if(n&1) B=mul(B,A);
A=mul(A,A);
n>>=1;
}
return B;
}
mat deal(mat x,ll k)
{
if(k==1) return x;
mat B=pow(x,(k+1)/2);
mat T=deal(x,k/2);
if(k%2==0) return cal(T,mul(B,T));//exp: s(6) = (1 + A^3) * s(3)
return cal(x,mul(cal(x,B),T));//exp: s(7) = A + (A + A^4) * s(3)
}
void solve()
{
mat A;
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
scanf("%I64d",&A.g[i][j]);
}
}
mat P=deal(A,k);
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
if(j==0)printf("%I64d",P.g[i][j]);
else printf(" %I64d",P.g[i][j]);
}
printf("\n");
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("coco.txt","r",stdin);
freopen("lala.txt","w",stdout);
#endif
while(scanf("%I64d%I64d%I64d",&N,&k,&m)!=EOF)
{
solve();
}
return 0;
}
hdu 2254 奥运
#include <stdio.h>
#include <string.h>
#include <cmath>
#define maxn 30
const int MOD = 2008;
int len;
__int64 city[maxn];
struct Mat
{
int mat[maxn][maxn];
}e,init;
int FindCity(__int64 x,bool flag)
{
int i;
for (i=0;i<len;i++)
if(city[i]==x)
return i;
if (flag)
{
city[len++] = x;
return len-1;
}
return 50;/*没找到城市*/
}
Mat operator+(Mat a,Mat b)
{
Mat c;
int i,j;
for (i=0;i<len;i++)
{
for(j=0;j<len;j++)
c.mat[i][j] = (a.mat[i][j]+b.mat[i][j])%MOD;
}
return c;
}
Mat operator*(Mat a,Mat b)
{
int i,j,k;
Mat c;
for (i=0;i<len;i++)
{
for (j=0;j<len;j++)
{
c.mat[i][j] = 0;
for(k=0;k<len;k++)
c.mat[i][j]+=(a.mat[i][k]*b.mat[k][j])%MOD;
}
}
return c;
}
Mat operator^(Mat a,int x)
{
Mat p = e,q = a;
while (x)
{
if(x&1)
p = p*q;
x>>=1;
q = q*q;
}
return p;
}
Mat solve(Mat x,int k)
{
if(k==1) return x;
Mat B=x^((k+1)/2);
Mat T=solve(x,k/2);
//if(k%2==0) return cal(T,mul(B,T));//exp: s(6) = (1 + A^3) * s(3)
if(k%2==0) return T+(B*T);
//return cal(x,mul(cal(x,B),T));//exp: s(7) = A + (A + A^4) * s(3)
return x+((x+B)*T);
}
int main()
{
__int64 v1,v2;
int t1,t2,i,j,n,k,c,locate1,locate2,sum;
Mat tem1,tem2;
for(i=0;i<maxn;i++)
for(j=0;j<maxn;j++)
e.mat[i][j] = (i==j);
while (scanf("%d",&n)!=EOF)
{
len = 0;
memset(&init,0,sizeof(init));
while (n--)
{
scanf("%I64d%I64d",&v1,&v2);
locate1 = FindCity(v1,1);
locate2 = FindCity(v2,1);
init.mat[locate1][locate2]++;
}
scanf("%d",&k);
while (k--)
{
scanf("%I64d%I64d%d%d",&v1,&v2,&t1,&t2);
if(t1>t2)
{
int temp=t1;
t1=t2;
t2=temp;
}
locate1 = FindCity(v1,0);
locate2 = FindCity(v2,0);
if(locate1==50||locate2==50||(t1==0&&t2==0))
printf("0\n");
else
{
if (t1>1)
{
tem1 = solve(init,t2);
tem2 = solve(init,t1-1);
sum = (tem1.mat[locate1][locate2]%MOD-tem2.mat[locate1][locate2]%MOD)%MOD;
}
else
{
tem1 = solve(init,t2);
sum = tem1.mat[locate1][locate2]%MOD;
}
if(sum<0)
sum+=MOD;
printf("%d\n",sum);
}
}
}
return 0;
}
vijosP1067 守望者的烦恼:
/* Author:GavinjouElephant
* Title:
* Number:
* main meanning:
*
*
*
*/
#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
const long long mod=7777777;
int Scan()//读入整数外挂.
{
int res = 0, ch, flag = 0;
if((ch = getchar()) == '-') //判断正负
flag = 1;
else if(ch >= '0' && ch <= '9') //得到完整的数
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9' )
res = res * 10 + ch - '0';
return flag ? -res : res;
}
void Out(int a) //输出外挂
{
if(a>9)
Out(a/10);
putchar(a%10+'0');
}
typedef vector<ll>vec;
typedef vector<vec>mat;
ll K,N;
mat mul(mat &A,mat & B)
{
mat C(A.size(),vec(B[0].size()));
for(int i=0;i<A.size();i++)
{
for(int k=0;k<B.size();k++)
{
for(int j=0;j<B[0].size();j++)
{
C[i][j]=(C[i][j]+A[i][k]*B[k][j])%mod;
}
}
}
return C;
}
mat pow(mat A,ll n)
{
mat B(A.size(),vec(A.size()));
for(int i=0;i<A.size();i++)
{
B[i][i]=1;
}
while(n>0)
{
if(n&1) B=mul(B,A);
A=mul(A,A);
n>>=1;
}
return B;
}
void solve()
{
mat A(K,vec(K));
for(int i=0;i<K;i++)
{
A[0][i]=1;
}
for(int i=1;i<K;i++)
{
A[i][i-1]=1;
}
A=pow(A,N);
mat B(K,vec(K));
B[0][0]=1;
A=mul(A,B);
cout<<A[0][0]<<endl;
}
int main()
{
while(cin>>K>>N)
{
solve();
}
return 0;
}
vijosP1049 送给圣诞夜的礼物(m次置换)
/* Author:GavinjouElephant
* Title:
* Number:
* main meanning:
*
*
*
*/
#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
int Scan()//读入整数外挂.
{
int res = 0, ch, flag = 0;
if((ch = getchar()) == '-') //判断正负
flag = 1;
else if(ch >= '0' && ch <= '9') //得到完整的数
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9' )
res = res * 10 + ch - '0';
return flag ? -res : res;
}
void Out(int a) //输出外挂
{
if(a>9)
Out(a/10);
putchar(a%10+'0');
}
int N,m,k;
int G[15][105];
class mat
{
public:
int g[105][105];
void Clear()
{
memset(g,0,sizeof(g));
}
};
mat mul(mat A,mat B)
{
mat C;
C.Clear();
for(int i=0;i<N;i++)
{
for(int k=0;k<N;k++)
{
for(int j=0;j<N;j++)
{
C.g[i][j]=(C.g[i][j]+A.g[i][k]*B.g[k][j]);
}
}
}
return C;
}
mat pow(mat A,ll n)
{
mat B;
B.Clear();
for(int i=0;i<N;i++)
{
B.g[i][i]=1;
}
while(n>0)
{
if(n&1) B=mul(B,A);
A=mul(A,A);
n>>=1;
}
return B;
}
void solve()
{
int t=k/m;
mat A;
A.Clear();
for(int j=0;j<N;j++)
{
A.g[j][G[m][j+1]-1]=1;
// cout<<G[m][j+1]<<endl;
}
A=pow(A,t);
int l=k%m;//最后的转换
if(l)
{
mat B;
B.Clear();
for(int j=0;j<N;j++)
{
B.g[j][ G[l][j+1]-1 ]=1;
}
A=mul(B,A);
}
//ans----->
mat C;
C.Clear();
for(int j=0;j<N;j++)
{
C.g[j][0]=j+1;
}
A=mul(A,C);
// cout<<"------->"<<endl;
// for(int i=0;i<N;i++)
// {
// for(int j=0;j<N;j++)
// {
// printf("%d ",A.g[i][j]);
// }
// printf("\n");
// }
for(int j=0;j<N;j++)
{
if(j==0)printf("%d",A.g[j][0]);
else printf(" %d",A.g[j][0]);
}
printf("\n");
}
int main()
{
while(scanf("%d%d%d",&N,&m,&k)!=EOF)
{
memset(G,0,sizeof(G));
for(int j=1;j<=N;j++)
{
G[0][j]=j;
}
int x;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=N;j++)
{
scanf("%d",&x);
G[i][j]=G[i-1][x];
}
}
solve();
}
return 0;
}
ps:多米诺骨牌的判断疑问
1.((~i)&j) == ((~i)&(SIZE-1))
对于第n-1列,那么我们就 例如 (从左往右看 转成从上往下看){001} -反码代表第n层状态{110} 因为只能打横铺不能打竖,否则就冲突,就判断j这个状态存不存在(110)这个状态.
2. for (int k=0; k<8; k++)isValid=isValid||(i&j)==validSet[k];
我们可以发现kuangbin巨巨写的const int validSet[]={0,3,6,12,15,24,27,30};两个两个1在移动为什么需要那么判呢,主要是判断是否可以放一个打竖的多米诺骨牌,这样的状态是允许的,因为是为了防止状态重复计算,而把打竖的抽离出来再这样判. 然后建图即可.