题意简述
一个三角形如图所示变化。初始状态(第0个状态)是一个大三角形,然后每一个三角形都会被4等分,分完就是下一个状态。求第 n n n( n n n的范围是 1 0 18 10^{18} 1018!!!)个状态中有多少个尖角朝上的三角形。对 1 0 9 + 7 10^9+7 109+7取模。
数据
输入
2
输出
10
思路
设第 i i i个状态中有 a [ i ] a[i] a[i]个朝上的, b [ i ] b[i] b[i]个朝下的。
首先每次4等分,三角形总数应该是不断 × 4 \times 4 ×4的。所以 a [ i ] + b [ i ] = 4 i a[i]+b[i]=4^i a[i]+b[i]=4i
我们发现,上一个状态中如果有一个朝下的,4等分之后会变成3个朝下的+1个朝上的。如果有一个朝上的,4等分之后会变成3个朝上的+1个朝下的。所以,我们珂以得到:
a [ i ] = 3 a [ i − 1 ] + b [ i − 1 ] b [ i ] = 3 b [ i − 1 ] + a [ i − 1 ] a[i]=3a[i-1]+b[i-1]\\ b[i]=3b[i-1]+a[i-1]\\ a[i]=3a[i−1]+b[i−1]b[i]=3b[i−1]+a[i−1]
这个式子有什么规律呢。。。
好像没有。
我们会想,如果知道
a
[
i
]
+
b
[
i
]
a[i]+b[i]
a[i]+b[i],那么只要知道
a
[
i
]
−
b
[
i
]
a[i]-b[i]
a[i]−b[i]就珂以直接求出
a
[
i
]
a[i]
a[i]和
b
[
i
]
b[i]
b[i]了。
那么我们减减试试吧。。。
a
[
i
]
−
b
[
i
]
=
3
(
a
[
i
−
1
]
−
b
[
i
−
1
]
)
+
(
b
[
i
−
1
]
−
a
[
i
−
1
]
)
=
2
(
a
[
i
−
1
]
−
b
[
i
−
1
]
)
a[i]-b[i]=3(a[i-1]-b[i-1])+(b[i-1]-a[i-1])=2(a[i-1]-b[i-1])
a[i]−b[i]=3(a[i−1]−b[i−1])+(b[i−1]−a[i−1])=2(a[i−1]−b[i−1])
显然,当
i
=
1
i=1
i=1时,
a
[
i
]
=
1
,
b
[
i
]
=
0
a[i]=1,b[i]=0
a[i]=1,b[i]=0
设
f
(
x
)
=
a
[
x
]
−
b
[
x
]
f(x)=a[x]-b[x]
f(x)=a[x]−b[x],那么由上面的式子得
f
(
1
)
=
1
f
(
x
)
=
2
f
(
x
−
1
)
f(1)=1\\ f(x)=2f(x-1)
f(1)=1f(x)=2f(x−1)
易得
f
(
x
)
=
2
x
f(x)=2^{x}
f(x)=2x。
故
a
[
i
]
−
b
[
i
]
=
2
x
a[i]-b[i]=2^x
a[i]−b[i]=2x
所以,
a
[
i
]
=
a
[
i
]
+
b
[
i
]
+
a
[
i
]
−
b
[
i
]
2
=
4
n
−
2
n
2
=
2
2
n
−
1
+
2
n
−
1
a[i]=\frac{a[i]+b[i]+a[i]-b[i]}{2}=\frac{4^n-2^n}{2}=2^{2n-1}+2^{n-1}
a[i]=2a[i]+b[i]+a[i]−b[i]=24n−2n=22n−1+2n−1。
打快速幂就珂以了。
代码:
#include<bits/stdc++.h>
#define int long long
#define mod 1000000007
using namespace std;
int p2(int p,int m)//快速求2的幂
{
int a=2;
int r=1;
while(p)
{
if (p&1) r=r*a%m;
a=a*a%m,p>>=1;
}
return r;
}
int n;
void Solve()
{
if (n==0)//特判这个!!!
{
puts("1");
return;
}
printf("%I64d\n",(p2(2*n-1,mod)+p2(n-1,mod))%mod);
}
main()
{
scanf("%I64d",&n);
Solve();
return 0;
}