CodeForces-185A Plant[矩阵快速幂]



Plant


题目传送门:CodeForces-185A

Time Limit 2000 ms
Memory limit 262144 kB



Problem Description:

Dwarfs have planted a very interesting plant, which is a triangle directed “upwards”. This plant has an amusing feature. After one year a triangle plant directed “upwards” divides into four triangle plants: three of them will point “upwards” and one will point “downwards”. After another year, each triangle plant divides into four triangle plants: three of them will be directed in the same direction as the parent plant, and one of them will be directed in the opposite direction. Then each year the process repeats. The figure below illustrates this process.

CodeForces-185A Plant[矩阵快速幂]_第1张图片
Help the dwarfs find out how many triangle plants that point “upwards” will be in n years.

Input:

The first line contains a single integer n ( 0   ≤   n   ≤   1 0 18 ) n (0 ≤ n ≤ 10^{18}) n(0n1018) — the number of full years when the plant grew.
Please do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use cin, cout streams or the %I64d specifier.

Output:

Print a single integer — the remainder of dividing the number of plants that will point “upwards” in n years by 1000000007 ( 1 0 9   +   7 ) 1000000007 (10^9 + 7) 1000000007(109+7).


Sample Input:

Sample One:

1

Sample Two:

2

Sample Output:

Sample One:

3

Sample Two:

10



题目大意:

i i i年的三角形是第 i − 1 i-1 i1年的三个复制一个倒置,问第 i i i年朝上的三角形 △ △ 个数有几个


思路:

一看 n n n的范围很容易想到应该是 O ( 1 ) O(1) O(1)或者 O ( l o g 2 n ) O(log_2n) O(log2n)
一开始以为第 i i i年的只是 i − 1 i-1 i1年多两行而已, O ( 1 ) O(1) O(1)公式交上去 w a wa wa了, O r z Orz Orz理解错题了
其实第 i i i年的三角形是第 i − 1 i-1 i1年的三个复制一个倒置,一个倒置在中心,三个倒置在三个顶点位置
B [ i ] B[i] B[i]表示第 i i i年所有小三角形的个数, F [ i ] F[i] F[i]表示第 i i i年所有 △ △ 的个数
由于第 i i i年的三角形是第 i − 1 i-1 i1年的三个复制一个倒置,则第 i i i年其中倒置的 i − 1 i-1 i1年会得到 B [ i − 1 ] − F [ i − 1 ] B[i-1]-F[i-1] B[i1]F[i1] △ △ ,即第i-1年的 ▽ ▽ 因此可以知道
B [ i ] = 4 ∗ B [ i − 1 ] F [ i ] = 3 ∗ F [ i − 1 ] + ( B [ i − 1 ] − F [ i − 1 ] ) F [ i ] = 2 ∗ F [ i − 1 ] + B [ i − 1 ] B[i] = 4*B[i-1]\\ F[i] = 3*F[i-1]+(B[i-1]-F[i-1])\\F[i]=2*F[i-1]+B[i-1] B[i]=4B[i1]F[i]=3F[i1]+(B[i1]F[i1])F[i]=2F[i1]+B[i1]
由于 n n n较大,所以可以考虑矩阵快速幂
由上述函数式可以得到系数矩阵
[ F [ n ] B [ n ] ] = [ 2 1 1 0 ] n ∗ [ F [ 0 ] B [ 0 ] ] \begin{bmatrix} F[n] \\ B[n] \end{bmatrix}= \begin{bmatrix} 2 & 1 \\ 1 & 0 \end{bmatrix}^n* \begin{bmatrix} F[0] \\ B[0] \end{bmatrix} [F[n]B[n]]=[2110]n[F[0]B[0]]
F [ 0 ] = B [ 0 ] = 1 F[0] = B[0] = 1 F[0]=B[0]=1



Code:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define  endc       std::ios::sync_with_stdio(false); // 关掉c++流
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  qwq(i, j)  for(int i = 0; i < j; ++i)
#define  qeq(i, j)  for(int i = 1; i <= j; ++i)
#define  isdigit(a) ((a)>='0'&&(a)<='9')
#define  xiao(a)    ((a)>='a'&&(a)<='z')
#define  da(a)      ((a)>='A'&&(a)<='Z')
#define  pii        pair
#define  lowbit(x)  x & (-x)
#define  fi         first
#define  se         second
#define  lson       id<<1
#define  rson       id<<1|1

typedef unsigned long long int ull;
typedef long long int ll;
const double eps  = 1e-8;
const double pi   = acos(-1.0);
const int    inf  = 0x3f3f3f3f;
const ll     INF  = 1e18 + 100;
const int    maxm = 1e6 + 6;
const int    maxn = 100 + 10;
const int    mod  = 1e9+7;
using namespace std;


int n, m, cas, tol = 0;
int head[maxn];
struct Edge {
     int u, v, w;}edge[maxm];

template<typename T>void re(T &x){
     x = 0; int f = 0; char ch = getchar();while(!isdigit(ch)){
     if(ch == '-') f=1; ch=getchar();}while(isdigit(ch)){
     x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}x = f?-x:x;}
// templateT fpow(T a, ll b) {T ans = 1; while(b) {if(b & 1) ans = a * ans % mod; a = a * a % mod; b >>= 1;}return ans;}
// inline void adde(int u, int v, int w) {edge[tol] = Edge{v, head[u], w}; head[u] = tol++;}
//POJ 3463 - Sightseeing

struct Matrix {
     
    ll m[2][2];
};

Matrix mmul(Matrix a, Matrix b) {
     
    Matrix ans;
    memset(ans.m, 0, sizeof(ans.m));
    for(int i = 0; i < 2; ++i) 
        for(int j = 0; j < 2; ++j)
            for(int k = 0; k < 2; ++k) 
                ans.m[i][j] = (ans.m[i][j]%mod+a.m[i][k]%mod*b.m[k][j]%mod)%mod;         
    return ans;
}

Matrix mpow(Matrix a, ll b) {
     
    Matrix ans;
    memset(ans.m, 0, sizeof(ans.m));
    for(int i = 0; i < 2; ++i)  ans.m[i][i] = 1;
    while(b) {
     
        if(b & 1)   ans = mmul(ans, a);
        a = mmul(a, a);
        b >>= 1;
    }
    return ans;
}

int main() {
     
    // 可以发现第n+1年就是三个第n年+一个第n年的倒数
    // 即F[n+1] = 3*F[n]+(B[n]+F[n]) 三个n年的上三角+一个n年的下三角
    // F[0] = B[0] = 1, // B[n]表示第n年的总三角形数
    // F[n] = 2 1  ^n   * F[0]
    // B[n]   0 4         B[0]
    ll n;
    cin >> n;
    if(n == 0) {
     
        cout << 1 <<endl;
        return 0;
    }
    Matrix ans;
    ans.m[0][0] = 2, ans.m[0][1] = 1, ans.m[1][0] = 0, ans.m[1][1] = 4;
    ans = mpow(ans, n);
    cout << (ans.m[0][0] + ans.m[0][1]) % mod << endl; 
    return 0;
}

你可能感兴趣的:(快速幂,快速幂)