分析
我们总共有n长的绳子,要求给绳子分段,每段都可以组成三角形,且所有三角形相似,三角形有顺序,问方案数
我们可以考虑一个
为周长为x的三角形的个数
考虑三边
如果
我们可以知道
(a最小为1,最大三边接近相等)
e如果
,我们知道
,所以
故,
可以由
递推上来(
为
)
神奇的我们还要考虑
时,这时候
所以
又因为
所以
的选择有
我们会发现,只有当
为奇数时才会产生贡献,所以我们需要减掉
为偶数时的贡献
这时候我们可以算出来所有的
对于一个周长为
的三角形,n长的绳子可以有
个
因为有顺序要求,我们可以考虑插空法,对于
个元素,我们有
个空,对于每个空,我们都可以选择插或者不插,所以贡献为
#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;
}
}