http://poj.org/problem?id=3734
无意中看到这题然后网上看了题解,正好可以用生成函数解决,也看到有用矩阵解决的,所以学习了用两种方法解决该问题。网上也有很多人建议用费马定理的,这里就不一一实现。
(1)用生成函数推出其公式,同斐波那契的通项式类似,推出其规律,然后编程就很容易。
#include <iostream>
const int MOD = 10007;
int tmod_n(int x, int n){
int ans = 1;
while(n > 0){
if(n%2 == 1){
ans = ans*x%MOD;
}
x = x*x%MOD;
n /= 2;
}
return ans;
}
int getAns(int k){
if(0 == k){
return 0;
}
if(1 == k){
return 2;
}
int ans = tmod_n(4, k-1) + tmod_n(2, k-1);
ans %= MOD;
return ans;
}
int main()
{
int t = 0;
std::cin>>t;
while(t--){
int x;
std::cin>>x;
std::cout<<getAns(x)<<std::endl;
}
return 0;
}
(2)找出其关系式,不用推其通项式,直接用矩阵实现,发现这样推的过程少很多,当然程序效率与上述相比也差很多,但我觉的矩阵给我们提供了一种很好解决问题的思路。下面的代码没经过仔细推敲,主要是学习式的应用一些知识。
//poj 3734 矩阵实现
//ans[i+1] = ans[i]*2 + 2*4^(i-2); i > 2
#include <iostream>
const int MOD = 10007;
class Matrix{
public:
Matrix(int r, int c);
Matrix(const Matrix& m);
Matrix& operator=(const Matrix&);
~Matrix();
public:
int row, cross;
int** mat;
};
inline Matrix::Matrix(int r, int c)
:row(r), cross(c){
mat = new int*[r];
for(int i = 0; i < r; i++){
mat[i] = new int[c];
}
}
Matrix::Matrix(const Matrix& m){
row = m.row;
cross = m.cross;
mat = new int*[row];
int r, c;
for(r = 0; r < row; r++){
mat[r] = new int[cross];
for(c = 0; c < cross; c++){
mat[r][c] = m.mat[r][c];
}
}
}
Matrix& Matrix::operator =(const Matrix& m){
if(this == &m){
return *this;
}
int r, c;
for(r = 0; r < row; r++){
delete []mat[r];
}
row = m.row;
cross = m.cross;
for(r = 0; r < row; r++){
mat[r] = new int[cross];
for(c = 0; c < cross; c++){
mat[r][c] = m.mat[r][c];
}
}
return *this;
}
Matrix::~Matrix(){
int r;
for(r = 0; r < row; r++){
delete []mat[r];
}
}
Matrix multMatrix(Matrix& mx, Matrix& my){
if(mx.cross != my.row){
Matrix mtmp(0, 0);
return mtmp;
}
Matrix tmp(mx.row, my.cross);
int r, c, t;
for(r = 0; r < tmp.row; r++){
for(c = 0; c < tmp.cross; c++){
tmp.mat[r][c] = 0;
for(t = 0; t < mx.cross; t++){
tmp.mat[r][c] += mx.mat[r][t]*my.mat[t][c];
}
tmp.mat[r][c] %= MOD; ///=========
}
}
return tmp;
}
int modMatrix(int n, Matrix m, int val)
{
Matrix orl(2, 1);
orl.mat[0][0] = val; orl.mat[1][0] = 2;
Matrix tmp(2, 2);
tmp.mat[0][0] = 1; tmp.mat[0][1] = 0;
tmp.mat[1][0] = 0; tmp.mat[1][1] = 1;
while(n > 0){
if(n%2==1){
tmp = multMatrix(tmp, m);
}
m = multMatrix(m, m);
n /= 2;
}
orl = multMatrix(tmp, orl);
return orl.mat[0][0];
}
int getAns(int n){
if(0 == n) return 0;
if(1 == n) return 2;
Matrix m(2, 2);
m.mat[0][0] = 2; m.mat[0][1] = 1;
m.mat[1][0] = 0; m.mat[1][1] = 4;
return modMatrix(n-1, m, 2)%MOD;
}
int main()
{
int t;
std::cin>>t;
while(t--){
int n;
std::cin>>n;
std::cout<<getAns(n)<<std::endl;
}
return 0;
}