hdu 4466 Triangle dp+数学

分析

我们总共有n长的绳子,要求给绳子分段,每段都可以组成三角形,且所有三角形相似,三角形有顺序,问方案数

我们可以考虑一个 F ( x ) F(x) 为周长为x的三角形的个数
考虑三边 a < = b < = c a<=b<=c
如果 b = = c b==c
我们可以知道 c [ x 1 2 , x 3 ] c\in[\frac{x-1}{2},\lceil\frac{x}{3}\rceil] (a最小为1,最大三边接近相等)
e如果 b < c b<c ,我们知道 a < = b < c a<=b<c ,所以 a + b > c 1 a+b>c-1
故, F ( x ) F(x) 可以由 F ( x 1 ) F(x-1) 递推上来( a + b > c 1 a+b>c-1 F ( x 1 ) F(x-1) )
神奇的我们还要考虑 a + b = c + 1 当a+b=c+1 时,这时候 c = x 1 2 c=\frac{x-1}{2}
所以 a + b = x x 1 2 a+b=x-\frac{x-1}{2}
又因为 a < = b a<=b
所以 a a 的选择有 x + 1 4 \frac{x+1}{4}
我们会发现,只有当 x x 为奇数时才会产生贡献,所以我们需要减掉 x x 为偶数时的贡献
这时候我们可以算出来所有的 F ( x ) F(x)

对于一个周长为 x x 的三角形,n长的绳子可以有 n x \frac{n}{x}
因为有顺序要求,我们可以考虑插空法,对于 n x \frac{n}{x} 个元素,我们有 n x 1 \frac{n}{x}-1 个空,对于每个空,我们都可以选择插或者不插,所以贡献为 2 n x 1 2^{\frac{n}{x}-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;
    }
}

发布了76 篇原创文章 · 获赞 5 · 访问量 1299

猜你喜欢

转载自blog.csdn.net/qq_43101466/article/details/103016643
今日推荐