[矩阵快速幂/推函数式]Codeforces185A Plant

来源:互联网 发布:java 获取temp目录 编辑:程序博客网 时间:2024/05/01 17:10

Codeforces185A Plant

题意:
就如图所示,求尖朝上的三角形有几个
思路1(推函数式):
这道题比起矩阵乘法更容易推出公式

年123总三角数2^2 = 42^4 = 162^16尖三角数31036

先将三角形从右下角开始,计有n层,我们可以得知(1~n)层有(1、2……n)个尖朝上的三角形,所以我们推出公式:(1+n)*n/2;
然后我们求n,我们可以发现1年后有2层,2年后有4层,3年后有8层……可以推出n年后有2^n层
所以最终公式为:(1 + 2^n)*2^(n-1);

代码1(推函数式):

/**************************************************************    Problem: CF_185A    User: soundwave    Language: C++    Result: Accepted    Time: 30ms    Memory: 2000KB****************************************************************///#pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include <stdio.h>using namespace std;typedef __int64 LL;const LL MOD = 1e9+7;//二分快速幂LL my_pow(LL x, LL c){    LL re = 1;    while(c>0){        if(c&1) re = (re*x) % MOD;        x = (x*x) % MOD;        c>>=1;    }    return re;}int main(){    LL n;    scanf("%I64d", &n);    if(n==0){        printf("1\n");        return 0;    }    LL re = my_pow(2,n-1);    printf("%I64d\n", (re*((re*2+1)%MOD)) % MOD);    return 0;}
思路2(矩阵快速幂):

矩阵乘法最重要的是要推出通项公式,这道题一看就是符合等差/等比数列的有规律的题
f(1)=3, f(2)=10, f(3)=36, f(4)=136;
根据前几项,可以推出通项公式:f(n) = 4*f(n-1) - 2^(n-1);
然后将之转化为矩阵乘法

4-102*

f(n-1)2^(n-1)=

f(n)2^n可以总结出

f(n)2^n
=

4-102
的(n-1)次幂

*

31还需要注意的一点是,当 n=1 时特判

代码2(矩阵快速幂):

/**************************************************************    Problem: CF_185A    User: soundwave    Language: C++    Result: Accepted    Time: 30ms    Memory: 2000KB****************************************************************///#pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include <stdio.h>#include <vector>/*通项公式:f(n) = 1                   (n==0);                 4*f(n-1) - 2^(n-1)  (n!=0);4 -1f(n-1)f(n)0 2    *2^(n-1)=2^n*/using namespace std;typedef vector<int>Vint;typedef vector<Vint>VVint;typedef __int64 LL;const int MOD = 1024;//矩阵乘法VVint calc(VVint &A, VVint &B){    VVint C(A.size(), Vint(A.size()));    for(int i=0; i<A.size(); i++)    for(int j=0; j<B[0].size(); j++)    for(int k=0; k<B.size(); k++)        C[i][j] = (C[i][j] + (A[i][k]*B[k][j])%MOD) % MOD;    return C;}//二分快速幂VVint my_pow(VVint &A, LL c){    VVint B(A.size(), Vint(A.size()));    if(c==0){        B[0][0] = 0;        B[0][1] = 1;        return B;    }    for(int i=0; i<A.size(); i++)        B[i][i] = 1;    while(c>0){        if(c&1) B = calc(B,A);        A = calc(A,A);        c>>=1;    }    return B;}int main(){    int t;    LL n;    scanf("%I64d", &n);    VVint A(2, Vint(2));    A[0][0]=4, A[0][1]=-1;    A[1][0]=0, A[1][1]=2;    A = my_pow(A, n-1);    LL re = 0;    re = ((A[0][0]*3)%MOD + A[0][1]) % MOD;    printf("%I64d\n", re);    return 0;}


0 0
原创粉丝点击