GDOI2018 滑稽子图 [斯特林数,树形DP]
传送门并没有
思路
见到那么小的\(k\)次方,又一次想到斯特林数。
\]
很套路地,考虑后面那个式子的组合意义:对于每一个点集的导出子图,选出\(i\)条边的方案数。
很套路地,我们想到树形DP。
设\(dp_{x,s,0/1}\)表示\(x\)子树内的所有非空点集的导出子图里选出\(s\)条边,点集里有/没有\(x\),的方案数。
每次加上一棵子树,就分三种情况考虑:只有原有的、只有新的、合在一起。其中最后一种要记入答案里。
代码
#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 101010
#define mod 998244353ll
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
inline void print(register int x)
{
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
int n,m,K;
struct hh{int t,nxt;}edge[sz<<1];
int head[sz],ecnt;
void make_edge(int f,int t)
{
edge[++ecnt]=(hh){t,head[f]};
head[f]=ecnt;
edge[++ecnt]=(hh){f,head[t]};
head[t]=ecnt;
}
ll dp[sz][15][2];
ll f[15][2];
int size[sz];
ll ans[15];
void dfs(int x,int fa)
{
dp[x][0][0]=0;dp[x][0][1]=1;++ans[0];
size[x]=1;
#define v edge[i].t
go(x) if (v!=fa)
{
dfs(v,x);
rep(i,0,14) rep(j,0,1) f[i][j]=dp[x][i][j];
rep(j,0,min(K,size[v])) (f[j][0]+=dp[v][j][0]+dp[v][j][1])%=mod;
rep(j,0,min(size[x],K))
{
rep(k,0,min(size[v],K-j))
{
ll S=(dp[v][k][0]+dp[v][k][1])%mod;
ll s1=dp[x][j][0]*S%mod,s2=dp[x][j][1]*(S+(k?dp[v][k-1][1]:0))%mod;
(f[j+k][0]+=s1)%=mod,
(f[j+k][1]+=s2)%=mod;
(ans[j+k]+=s1+s2)%=mod;
}
}
rep(i,0,K) rep(j,0,1) dp[x][i][j]=f[i][j];
size[x]+=size[v];
}
#undef v
}
void solve(){dfs(1,0);}
ll S[15][15];
int main()
{
file();
int x,y;
read(n,m,K);
rep(i,1,n-1) read(x,y),make_edge(x,y);
solve();
S[0][0]=1;
rep(i,1,K)
rep(j,1,i)
S[i][j]=(S[i-1][j-1]+S[i-1][j]*j%mod)%mod;
ll fac=1,Ans=0;
rep(i,1,K) fac=fac*i%mod,(Ans+=fac*S[K][i]%mod*ans[i]%mod)%=mod;
cout<<Ans;
return 0;
}
GDOI2018 滑稽子图 [斯特林数,树形DP]的更多相关文章
- BZOJ.2159.Crash的文明世界(斯特林数 树形DP)
BZOJ 洛谷 挺套路但并不难的一道题 \(Description\) 给定一棵\(n\)个点的树和\(K\),边权为\(1\).对于每个点\(x\),求\(S(x)=\sum_{i=1}^ndis( ...
- [BZOJ2159]Crash的文明世界(斯特林数+树形DP)
题意:给定一棵树,求$S(i)=\sum_{j=1}^{n}dist(i,j)^k$.题解:根据斯特林数反演得到:$n^m=\sum_{i=0}^{n}C(n,i)\times i!\times S( ...
- bzoj 2159 Crash 的文明世界 && hdu 4625 JZPTREE ——第二类斯特林数+树形DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159 学习材料:https://blog.csdn.net/litble/article/d ...
- P4827 [国家集训队] Crash 的文明世界(第二类斯特林数+树形dp)
传送门 对于点\(u\),所求为\[\sum_{i=1}^ndis(i,u)^k\] 把后面那堆东西化成第二类斯特林数,有\[\sum_{i=1}^n\sum_{j=0}^kS(k,j)\times ...
- 【BZOJ2159】Crash的文明世界 斯特林数+树形dp
Description Crash 小朋友最近迷上了一款游戏--文明5(Civilization V).在这个游戏中,玩家可以建立和发展自己的国家,通过外交和别的国家交流,或是通过战争征服别的国家.现 ...
- bzoj 2159 Crash 的文明世界 & hdu 4625 JZPTREE —— 第二类斯特林数+树形DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159 使用公式:\( n^{k} = \sum\limits_{i=0}^{k} S(k,i ...
- BZOJ 2159: Crash 的文明世界(组合数学+第二类斯特林数+树形dp)
传送门 解题思路 比较有意思的一道数学题.首先\(n*k^2\)的做法比较好想,就是维护一个\(x^i\)这种东西,然后转移的时候用二项式定理拆开转移.然后有一个比较有意思的结论就是把求\(x^i\) ...
- BZOJ2159 Crash 的文明世界 【第二类斯特林数 + 树形dp】
题目链接 BZOJ2159 题解 显然不能直接做点分之类的,观察式子中存在式子\(n^k\) 可以考虑到 \[n^k = \sum\limits_{i = 0} \begin{Bmatrix} k \ ...
- BZOJ 2159: Crash 的文明世界 第二类斯特林数+树形dp
这个题非常巧妙啊~ #include <bits/stdc++.h> #define M 170 #define N 50003 #define mod 10007 #define LL ...
随机推荐
- C# UpdatePanel加载完毕回调JS
如果 我们想UpdatePanel加载完成后做一些事情 需要使用js <script type="text/javascript"> //给ScriptManager的 ...
- SpringBoot入门笔记(二)、使用fastjson
1.添加fastjson配置 <dependency> <groupId>com.alibaba</groupId> <artifactId>fastj ...
- 32. Springboot 系列(八)动态Banner与图片转字符图案的手动实现
使用过 Springboot 的对上面这个图案肯定不会陌生,Springboot 启动的同时会打印上面的图案,并带有版本号.查看官方文档可以找到关于 banner 的描述 The banner tha ...
- VS中ipch文件夹和sdf文件的处理方式
ipch文件夹和sdf是VS产生的预编译头文件和智能提示信息,对编码没有影响,可存放在固定的位置,定期进行清理
- MySQL对表数据操作
一: 修改表信息 1.修改表名 alter table test_a rename to sys_app; 2.修改表注释 alter table sys_application comment '系 ...
- sql连接:inner join on, left join on, right join on使用详解
点击打开原文 inner join(等值连接) 只返回两个表中联结字段相等的行 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包 ...
- js开发模式
js中的开发模式进化史: js中有最初的只能由基本数据类型描述——>单例模式-->工厂模式-->构造函数模式-->原型模式-->各个模式相结合的混合模式,下面我会给大家逐 ...
- retrofit动态代理
https://blog.csdn.net/dalong3976/article/details/83479816
- 算法-链的操作(一)-合并两个排序的链接(no.25)
合并两个排序的链接(no.25) 把下面连个排好序的链,从小到大排序链接. list1 : 1 -> 6 -> 8 list2 : 2-> 5 -> 9 def merge(h ...
- Required String parameter 'images' is not present
后台控制层控制为非必填即可: @RequestMapping("/addDo") @SJson @SLog(description = "Car_main") ...