分析
我们总共有n长的绳子,要求给绳子分段,每段都可以组成三角形,且所有三角形相似,三角形有顺序,问方案数
我们可以考虑一个
F
(
x
)
F(x)
F(x)为周长为x的三角形的个数
考虑三边
a
<
=
b
<
=
c
a<=b<=c
a<=b<=c
如果
b
=
=
c
b==c
b==c
我们可以知道
c
∈
[
x
−
1
2
,
⌈
x
3
⌉
]
c\in[\frac{x-1}{2},\lceil\frac{x}{3}\rceil]
c∈[2x−1,⌈3x⌉](a最小为1,最大三边接近相等)
e如果
b
<
c
b<c
b<c,我们知道
a
<
=
b
<
c
a<=b<c
a<=b<c,所以
a
+
b
>
c
−
1
a+b>c-1
a+b>c−1
故,
F
(
x
)
F(x)
F(x)可以由
F
(
x
−
1
)
F(x-1)
F(x−1)递推上来(
a
+
b
>
c
−
1
a+b>c-1
a+b>c−1为
F
(
x
−
1
)
F(x-1)
F(x−1))
神奇的我们还要考虑
当
a
+
b
=
c
+
1
当a+b=c+1
当a+b=c+1时,这时候
c
=
x
−
1
2
c=\frac{x-1}{2}
c=2x−1
所以
a
+
b
=
x
−
x
−
1
2
a+b=x-\frac{x-1}{2}
a+b=x−2x−1
又因为
a
<
=
b
a<=b
a<=b
所以
a
a
a的选择有
x
+
1
4
\frac{x+1}{4}
4x+1
我们会发现,只有当
x
x
x为奇数时才会产生贡献,所以我们需要减掉
x
x
x为偶数时的贡献
这时候我们可以算出来所有的
F
(
x
)
F(x)
F(x)
对于一个周长为
x
x
x的三角形,n长的绳子可以有
n
x
\frac{n}{x}
xn个
因为有顺序要求,我们可以考虑插空法,对于
n
x
\frac{n}{x}
xn个元素,我们有
n
x
−
1
\frac{n}{x}-1
xn−1个空,对于每个空,我们都可以选择插或者不插,所以贡献为
2
n
x
−
1
2^{\frac{n}{x}-1}
2xn−1
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T>
void out(T x) { cout << x << endl; }
ll fast_Pow(ll a, ll b, ll p) {ll c = 1; while(b) { if(b & 1) c = c * a % p; a = a * a % p; b >>= 1;} return c;}
ll exgcd(ll a, ll b, ll &x, ll &y) { if(!b) {x = 1; y = 0; return a; } ll gcd = exgcd(b, a % b, y, x); y-= a / b * x; return gcd; }
const int N = 5e6 + 10;
const int mod = 1e9 + 7;
int dp[N], Pow[N];
void init()
{
Pow[0] = 1;
dp[0] = dp[1] = dp[2] = 0;
dp[3] = 1;
for(int i = 1; i < N; i ++)
Pow[i] = (Pow[i - 1] * 2ll) % mod;
for(int i = 4; i < N; i ++)
{
dp[i] = dp[i - 1] + (i - 1) / 2 - i / 3 + (i % 3 ? 0 : 1);
if(!(i & 1))
dp[i] -= (i + 1) / 4;
dp[i] = (dp[i] % mod + mod) % mod;
}
for(int i = 2; i < N; i ++)
for(int j = 2 * i; j < N; j += i)
dp[j] = (dp[j] - dp[i] + mod) % mod;
}
int main()
{
ios::sync_with_stdio(false);
int n, td = 0;
init();
while(cin >> n)
{
td ++;
cout << "Case " << td << ": ";
ll ans = 0;
for(int i = 1; i * i <= n; i ++)
{
if(n % i == 0)
{
ans = (ans + 1ll * Pow[n / i - 1] * dp[i] % mod) % mod;
if(i * i != n)
ans = (ans + 1ll * Pow[i - 1] * dp[n / i] % mod) % mod;
}
}
cout << ans << endl;
}
}