Time Limit | 2000 ms |
---|---|
Memory limit | 262144 kB |
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.
Help the dwarfs find out how many triangle plants that point “upwards” will be in n years.
The first line contains a single integer n ( 0 ≤ n ≤ 1 0 18 ) n (0 ≤ n ≤ 10^{18}) n(0 ≤ n ≤ 1018) — 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.
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 One:
1
Sample Two:
2
Sample One:
3
Sample Two:
10
第 i i i年的三角形是第 i − 1 i-1 i−1年的三个复制一个倒置,问第 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 i−1年多两行而已, O ( 1 ) O(1) O(1)公式交上去 w a wa wa了, O r z Orz Orz理解错题了
其实第 i i i年的三角形是第 i − 1 i-1 i−1年的三个复制一个倒置,一个倒置在中心,三个倒置在三个顶点位置
用 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 i−1年的三个复制一个倒置,则第 i i i年其中倒置的 i − 1 i-1 i−1年会得到 B [ i − 1 ] − F [ i − 1 ] B[i-1]-F[i-1] B[i−1]−F[i−1]个 △ △ △,即第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]=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]
由于 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
#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;
}