1. 程式人生 > 實用技巧 >樹 (DP,dfs序,組合數學,思維)

樹 (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;
}
組合數