您的位置:首页 > 其它

POJ 3420

2016-06-11 17:39 309 查看
题意:给你4*n个格子,放满1*2的物体,问有多少种放法?

题解:我的做法比较麻烦 首先考虑f(n=1)=1 f(2)=5

后面的可以由前面的递推 例如 f(18)=f(17) + f(16) * 2 + (f(1)+f(3)+...+f(15)) * 2 + (f(0)+f(2)+f(4)+...+f(14)) * 3;

由之前的n加一整块得来

由于n比较大 所以用矩阵快速幂来搞 另外还要维护奇数前缀和与偶数前缀和  

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<deque>
#define mem(x,y) memset(x,y,sizeof(x))
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pii;
#define bug puts("===========");
#define zjc puts("");
const double pi=(acos(-1.0));
const double eps=1e-8;
const ll INF=1e18+10;
const ll inf=1e9+10;
const int maxn=100+10;
const int mod=1e9+7;
/*=======================================*/

/*=========================================
矩阵运算
乘法复杂度:O(N^3)
=========================================*/
const int Mn = 101;
const int Mm = 101;
typedef long long mytype;
#define wlhz %Mmod;
ll Mmod=1e9+7;
struct Matrix {
int n, m;
mytype a[Mn][Mm];
void init() { memset(a, 0, sizeof(a)); }
Matrix(int n=Mn,int m=Mm):n(n),m(m) {}
void U(int Size){///将现有矩阵转换为一个同等大小的单位矩阵
n=m=Size;
init();
for (int i = 0; i < n; i++) a[i][i] = 1;
}
Matrix unit() {///构造一个同等大小的单位矩阵
Matrix tmp(n,n);
tmp.init();
for (int i = 0; i < n; i++) tmp.a[i][i] = 1;
return tmp;
}
Matrix operator + (const Matrix &b) const {
Matrix tmp(n,m);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) tmp.a[i][j] = (a[i][j] + b.a[i][j])wlhz
return tmp;
}
Matrix operator - (const Matrix &b) const {
Matrix tmp(n,m);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) tmp.a[i][j] = (a[i][j] - b.a[i][j])wlhz
return tmp;
}
Matrix operator * (const Matrix &b) const {
Matrix tmp(n,b.m); tmp.init();
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (a[i][j])
for (int k = 0; k < b.m; k++)
tmp.a[i][k] = (tmp.a[i][k] + a[i][j] * b.a[j][k]) wlhz
return tmp;
}
Matrix operator * (const mytype &b) const{
Matrix tmp(n,m);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
tmp.a[i][j] = a[i][j] * b wlhz
}
return tmp;
}
Matrix operator !() {///矩阵转置
Matrix tmp(m,n);
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
tmp.a[j][i] = a[i][j];
return tmp;
}
friend Matrix pow(Matrix a, mytype b) {///矩阵快速幂
Matrix tmp=a.unit();
for (; b>0; b>>=1,a=a*a) if(b&1) tmp=tmp*a;
return tmp;
}
void IN(){
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++) scanf("%lld",&a[i][j]);
}
void OT(){
for(int i=0; i<n; i++)
for(int j=0; j<m; j++) printf("%lld%c",a[i][j]," \n"[j==m-1]);
}
};
Matrix A,B;
int dp[3];
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)&&n+m){
Mmod=m;
dp[1]=1; dp[2]=5;
if(n<=2){
printf("%d\n",dp
%m);
continue;
}
A.n=1; A.m=5;
A.a[0][0]=dp[2]; A.a[0][1]=dp[1]; A.a[0][2]=0; A.a[0][3]=0; A.a[0][4]=1;
B.n=B.m=5;
B.a[0][0]=1+4; B.a[0][1]=1; B.a[0][2]=1; B.a[0][3]=0; B.a[0][4]=0;
B.a[1][0]=4+2; B.a[1][1]=4; B.a[1][2]=0; B.a[1][3]=1; B.a[1][4]=0;
B.a[2][0]=2+3; B.a[2][1]=2; B.a[2][2]=1; B.a[2][3]=0; B.a[2][4]=0;
B.a[3][0]=3+2; B.a[3][1]=3; B.a[3][2]=0; B.a[3][3]=1; B.a[3][4]=0;
B.a[4][0]=3+2; B.a[4][1]=2; B.a[4][2]=0; B.a[4][3]=0; B.a[4][4]=1;
A=A*pow(B,(n-1)/2);
printf("%d\n",A.a[0][n%2]);

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  矩阵快速幂