传送门:POJ3734
题意:用红黄绿蓝四种色块组成长为n的线段,要求红色和绿色的色块数为偶数,问有多少种组成方法。
思路:我是看着大白上的推出来的矩阵快速幂的公式做的,但是我看discuss里各路大神直接推出了线性公式,根本不用矩阵。。话说生成函数是个什么鬼啊。。要学的东西好多啊。。
想知道具体思路的请自行查阅挑战程序设计第二版,上面分析的很清楚了。
代码:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
const int mod = 10007;
typedef long long ll;
typedef vector<int> vec;
typedef vector<vec> mat;//用二维vector来表示矩阵
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 poww(mat &A,ll n)
{
mat B(A.size(),vec(A[0].size()));
for(int i=0;i<B.size();i++)
B[i][i]=1;
while(n)
{
if(n&1) B=mul(B,A);
A=mul(A,A);
n>>=1;
}
return B;
}
int main()
{
int T,n;
cin>>T;
while(T--)
{
cin>>n;
mat A(3,vec(3));
A[0][0]=2;A[0][1]=1;A[0][2]=0;
A[1][0]=2;A[1][1]=2;A[1][2]=2;
A[2][0]=0;A[2][1]=1;A[2][2]=2;
A=poww(A,n);
cout<<A[0][0]<<endl;
}
}
写这个题学到了vector套vector当二维数组用的骚方法,这样两个维度都可以动态申请,而不必提前确定好。