树 (DP,dfs序,组合数学,思维)

题目:传送门

题意

 

1 <= n, k <= 300

思路

这题邓老师用的是 dfs 序做的 --> 戳我

用dfs序的话,是 o(nk)的,复杂度略高

这题还可以用另一种思维做;

可以将染色转化为,将一颗树分成若干连通块,连通块里的颜色都相同,不同连通块的颜色不同;

把一颗树分成不同的两个连通块就是删除一条边,那分成 x 块就是删掉 x - 1 条边;那方案数就是 C(n - 1, x - 1);

然后选 x 种颜色有 C(k, x) 种方案,将 x 种颜色染到 x 个连通块上有 x! 种方案;

这样的复杂度是很接近 o(n) 的

 

#include <bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define UI unsigned int
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF 0x3f3f3f3f
#define inf LLONG_MAX
#define PI acos(-1)
#define fir first
#define sec second
#define lb(x) ((x) & (-(x)))
#define dbg(x) cout<<#x<<" = "<<x<<endl;
using namespace std;

const int N = 1e6 + 5;

const LL mod = 1e9 + 7;

int n, k, u, v;

LL dp[305][305];

void solve() {

    scanf("%d %d", &n, &k);

    rep(i, 1, n - 1) scanf("%d %d", &u, &v);
    
    dp[0][0] = 1LL;
    
    rep(i, 1, n) rep(j, 1, k) dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1] * (k - j + 1) % mod) % mod;
    
    LL ans = 0LL;
    
    rep(i, 1, k) ans = (ans + dp[n][i]) % mod;
    
    printf("%lld\n", ans);
    
}


int main() {

//    int _; scanf("%d", &_);
//    while(_--) solve();

    solve();

    return 0;
}
dfs序
#include <bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define UI unsigned int
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF 0x3f3f3f3f
#define inf LLONG_MAX
#define PI acos(-1)
#define fir first
#define sec second
#define lb(x) ((x) & (-(x)))
#define dbg(x) cout<<#x<<" = "<<x<<endl;
using namespace std;

const int N = 1e6 + 5;

const LL mod = 998244353;

int ans[10];

void calr(int x) {

    for(int l = 1, r; l <= x; l = r + 1) {

        r = x / (x / l);



    }

}

void call(int x) {



}


void solve() {

    int l, r;

    scanf("%d %d", &l, &r);

    calr(r);

    call(l - 1);

    rep(i, 1, 9) printf("%d\n", ans[i])

}


int main() {

//    int _; scanf("%d", &_);
//    while(_--) solve();

    solve();

    return 0;
}
组合数

 

posted on 2020-09-17 09:31  Willems  阅读(176)  评论(0编辑  收藏  举报

导航