Codeforces185A Plant
题意:
就如图所示,求尖朝上的三角形有几个
思路1(推函数式):
这道题比起矩阵乘法更容易推出公式
年 | 1 | 2 | 3 |
总三角数 | 2^2 = 4 | 2^4 = 16 | 2^16 |
尖三角数 | 3 | 10 | 36 |
先将三角形从右下角开始,计有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 | -1 |
0 | 2 |
f(n-1) |
2^(n-1) |
f(n) |
2^n |
f(n) |
2^n |
4 | -1 |
0 | 2 |
*
3 |
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 -1 f(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;
}