HDU 5136 Yue Fei's Battle

5247 단어 dp두 갈래 나무
전송문 제목: 직경에 K개의 점이 있는 서로 다른 구조의 나무 개수를 구한다(점마다 3을 초과하지 않는다).두 갈래 나무는 점마다 3을 넘지 않고 지름을 중간에서 자르면 양쪽이 두 갈래 나무다.dp[i]= 깊이가 i인 서로 다른 구조의 두 갈래 나무 개수를 설정합니다.sum[i]= 깊이가 i를 초과하지 않는 서로 다른 구조의 두 갈래 나무 개수.그러면 두 갈래 나무의 두 갈래는 세 가지 상황이 있다. 한 갈래의 깊이는 i-3-1이고 다른 갈래의 깊이는 i-3-1보다 작으며 dp[i-31]의sum[i-3]방법이 있다.두 지점의 깊이는 모두 i-31이다. 두 지점은 다르고 dp[i-31]∗(dp[i-31]-31)/2가지 방법이 있다.두 가지와 마찬가지로 dp[i-31]의 방법이 있다.dp[i]=dp[i−1]∗sum[i−2]+dp[i−1]∗(dp[i−1]+1)/2
i=K/2가 짝수일 때 양쪽의 두 갈래 나무의 깊이는 모두 K/2이고 양쪽이 같을 수도 있고 다를 수도 있음을 고려하면 방안수는 dp[i]∗(dp[i]+1)/2이다.
K가 홀수이면 중간 점은 3개의 브랜치를 연결하고 최소 2개의 브랜치 깊이는 K/2입니다.3개의 지점에 하나의 지점 깊이가 K/2보다 작으면 방안수 dp[i](dp[i]+1)/2∗sum[i-1]은 3개의 지점 깊이가 모두 K/2이다. 3개의 지점이 모두 같으면 방안수 dp[i]는 3개의 지점 2개가 같고 방안수는 dp[i]∗(dp[i]-1)이다. 3개의 지점이 서로 다르면 방안수 C(dp[i], 3)의 모든 상황을 합치면 된다.
#include <bits/stdc++.h>
using namespace std;
#define prt(k) cerr<<#k" = "<<k<<endl

typedef long long ll;
const ll mod = 1e9 + 7;
ll pmod(ll a, ll n)
{
    ll ret = 1;
    for (; n; n>>=1, a=a*a%mod)
        if (n&1)
        ret = ret * a % mod;
    return ret;
}
ll getinv(ll a)
{
    return pmod(a, mod - 2);
}
const int N = 100100;
ll dp[N + 5], sum[N + 5];
const ll inv2 = getinv(2);
ll sub(ll a, ll b)
{
    return (a - b + mod) % mod;
}
void init()
{
    dp[0] = 1;
    dp[1] = 1;
    sum[0] = 1;
    sum[1] = 2;
    for (int i=1;i<N;i++)
    {
        dp[i+1] = (dp[i] * sum[i-1] % mod);
        dp[i+1] = (dp[i+1] + (dp[i] + 1)%mod * dp[i] % mod * inv2 % mod) % mod;
        sum[i+1] = (sum[i] + dp[i+1]) % mod;
    }
}
ll C3(ll a)
{
    return ((a*sub(a,1)%mod) * sub(a,2) % mod) * getinv(6) % mod;
}
ll f(int K)
{
    int i = K / 2;
    ll ans = ((dp[i] * (dp[i] +  1)%mod) % mod * inv2 % mod ) % mod;
    ll tmp = ans;
    if (K%2==0) {
        return ans;
    }
    ans = (ans * sum[i-1]) % mod;
    ans = (ans + dp[i]) % mod;
    ans = (ans + (dp[i]-1+mod)%mod * dp[i] % mod) % mod;
    ans = (ans + C3(dp[i])) % mod;
    return ans;
}
int main()
{
    int K;
    init();
    while (cin>>K, K)
    {
        ll ans = f(K);
        cout<<ans<<endl;
    }
    return 0;
}

좋은 웹페이지 즐겨찾기