Tree Cutting HDU - 5909(树形DP+FWT优化)

Tree Cutting

题目链接:HDU - 5909

题意:有一个连通图,n个点,n-1条边(就是一棵树),每个节点有一个权值,一棵树的价值是其节点(包括本身及其子节点)的权值的异或和;求价值为[0, m)的树有多少颗?(这里所谓的树其实是原连通图的任意子图);

思路:最先想到树形DP;

令:dp[u][i]表示u节点为根的价值为i的树的数量;

dp[u][j^k]=dp[u][j^k]+dp[u][j]*dp[son][k];也就是:   

dp[u][j^k]+\sum_{j*k=0} dp[u][j]*dp[son][k];

\sum_{j*k=0} dp[u][j]*dp[son][k]   的复杂度是O(m^2); 直接算就超时了;这里就用到了FWT,将复杂度优化为O(nmlogm);

至于FWT是什么,我也讲不清楚,大家可以自行百度,在下太弱了,讲不明白了(其实是自己也没明白);

#include 
using namespace std;
vector vec[1100];
typedef long long ll;
const ll mod=1e9+7;
const ll ret=(mod+1)/2;
ll val[1100], ans[1100], dp[1100][1100], temp[1100];
int n, m;
void FWT(ll *a, int n){
	for(int i=1; i

还有一个点分治解法还没学会,等学会再补

你可能感兴趣的:(怒刷DP)