Codeforces Round #548 (Div. 2) C dp or 排列组合

https://codeforces.com/contest/1139/problem/C

题意

一颗有n个点的树,需要挑选出k个点组成序列(可重复),按照序列的顺序遍历树,假如经过黑色的边,那么这个序列就是好的,问有多少个好的序列

题解

  • 黑边不连,红边连,假如两个点不在同一并查集,那么一定经过黑边
  • 定义\(dp[i][j][k]\)为选择前i个点,起始点为j,是否已经经过黑边(k)的方案数
  • \(dp[i-1][j][0]*(n-N[fin(j)])+dp[i-1][j][1]*n - > dp[i][j][1]\)
  • \(dp[i-1][j][0]*N[fin(j)] - > dp[i][j][0]\)

代码

#include<bits/stdc++.h>
#define MOD 1000000007
using namespace std;
int fa[100005],i,j,n,m,u,v,w;
int fin(int u){return fa[u]==u?u:fa[u]=fin(fa[u]);}
void merge(int u,int v){
    int x=fin(u),y=fin(v);
    if(x!=y)fa[x]=y;
}
long long dp[100005][3],ans,N[100005];
int main(){
    cin>>n>>m;
    for(i=1;i<=n;i++)fa[i]=i;
    for(i=0;i<n-1;i++){
        scanf("%d%d%d",&u,&v,&w);
        if(!w)merge(u,v);
    }
    for(i=1;i<=n;i++){N[fin(i)]++;dp[i][0]=1;}
    for(i=2;i<=m;i++){
        for(j=1;j<=n;j++){
            dp[j][1]=(dp[j][0]*((n-N[fin(j)]+MOD)%MOD)%MOD+dp[j][1]*n%MOD)%MOD;
            dp[j][0]=(dp[j][0]*N[fin(j)])%MOD;
        }
    }
    for(i=1;i<=n;i++)
        ans=(ans+dp[i][1])%MOD;
    cout<<ans;
}

原文地址:https://www.cnblogs.com/VIrtu0s0/p/10630874.html

时间: 2024-07-30 11:51:47

Codeforces Round #548 (Div. 2) C dp or 排列组合的相关文章

Codeforces Round #261 (Div. 2) E (DP)

E. Pashmak and Graph Pashmak's homework is a problem about graphs. Although he always tries to do his homework completely, he can't solve this problem. As you know, he's really weak at graph theory; so try to help him in solving the problem. You are

Codeforces Round #536 (Div. 2) E dp + set

https://codeforces.com/contest/1106/problem/E 题意 一共有k个红包,每个红包在\([s_i,t_i]\)时间可以领取,假如领取了第i个红包,那么在\(d_i\)后才能领取下一个红包,每个红包价值\(w_i\),对方假如有机会领取红包他一定会领取,你有m次阻止对方领取的机会,问对方最少可以拿到多少红包 题解 定义dp[i][j]为前i秒用了j次机会让对方拿到最小价值的红包 \(dp[i][j] - > dp[i+1][j+1]\) 假如使用阻止 \(d

Codeforces Round #156 (Div. 1)A dp

//对每个数进行一个编号, //dp[i][j]表示第i个数其前面是第j个数得到的最长子序列 //dp[i][j] =  dp[i][j] = dp[last[j]][map[num[i]]] + 1; //last[j]是编号为j的数的最后出现的位置 //map[num[i]]第i个数的编号 #include<iostream> #include<cstdio> #include<cstring> using namespace std ; const int max

Codeforces Round #144 (Div. 1) B dp

//第i列和第i+n的涂色个数是相同的,所以只需要处理前n列 //dp[i][j]表示前i列有j个涂色的方法数 //dp[i][j] += dp[i-1][s]*pow(c[n][s] , m/n) //c[n][s] 表示从n个数中取s的组合数 #include<cstdio> #include<cstring> #include<iostream> using namespace std ; const int maxn = 110 ; const __int64

Codeforces Round #162 (Div. 1) B dp

//存入所有数的素数因数 //若两个数不互质,那么他们之间必然有素数因数 //dp[i][0]表示第i个数不选前i个数中能得到的最长序列 //dp[i][1]表示选了第i个数 //dp[i][0] = max(dp[i-1][0] , dp[i-1][1]) //dp[i][1] = max(dp[pos][1] + 1 ,dp[i][1] ); //pos位第i个数的质数因子出现的最后一个位置 #include<cstdio> #include<cstring> #include

Codeforces Round #302 (Div. 2)——C dp—— Writing Code

Programmers working on a large project have just received a task to write exactly m lines of code. There are n programmers working on a project, the i-th of them makes exactly ai bugs in every line of code that he writes. Let's call a sequence of non

Codeforces Round #363 (Div. 2) C dp或贪心 两种方法

Description Vasya has n days of vacations! So he decided to improve his IT skills and do sport. Vasya knows the following information about each of this n days: whether that gym opened and whether a contest was carried out in the Internet on that day

Codeforces Round #427 (Div. 2) D dp

D. Palindromic characteristics 题意:求给定字符串每阶回文子串有多少个. tags:根本没想到 dp..直接看官方题解吧 dp[i][j] 代表第 i 个字符到第 j 个字符的子串是几阶回文. Solution. Let's calculate the following dp. dp[l][r] is the maximum k such that the substring built from characters from l to r is k-palin

Codeforces Round #548 (Div. 2) F splay(新坑) + 思维

https://codeforces.com/contest/1139/problem/F 题意 有m个人,n道菜,每道菜有\(p_i\),\(s_i\),\(b_i\),每个人有\(inc_j\),\(pref_j\),一个人可以买一道菜的条件是 1. \(p_i \leq inc_j \leq s_i\) 2. \(|b_i - pref_j| \leq inc_j-p_i\) ,问每个人分别能买多少道菜 题解 转化一下公式 \(p_i \leq inc_j \leq s_i\) 下面两个满