51nod 1446 限制價值樹

2021-08-16 03:22:03 字數 2715 閱讀 5107

有n個點(n<=40)標記為0,1,2,…n-1,每個點i有個價值val[i],如果val[i]=-1那麼這個點被定義為bad,否則如果val[i] >=0那麼這個點為定義為good。現在給這n個點間連上n-1條邊,使它們構成乙個生成樹,定義樹中的點為great點當且僅當這個點本身是good點且與其相鄰的點中至少有另乙個good點。樹的價值等於樹中所有great點的價值和。定義限制價值樹是指價值不大於maxval的樹,問對給定的val與maxval,一共有多少種不同的限制**樹?由於答案太大,可取

modulo 1,000,000,007後的結果。

說明:兩棵樹是不同的,指兩棵樹的邊集不同,注意這裡的邊都是無向邊。

其實我們可以發現,所有的good點和bad點其實都是一樣的,是沒有區別的

我們只需要對於他們,排列組合一下求方案就好了

如果我們知道,有f[

i]f [i

]表示剛好有i個點是great點

並且我們還知道乙個h[

i]h [i

]表示有多少種方案,使得選了i個good點,並且他們的值合法

那麼乘起來就可以了 h[

i]h [i

]的計算顯然可以用折半搜尋來完成 至於f

[i] f[i

]則需要容斥 考慮g

[i] g[i

]表示至少i個點不是great點,就是說著i個只可以和bad相連

那麼這個可以用矩陣樹定理來做。。

sb的我一開始不記得要用余子式,直接就用原來的行列式了

於是就可以容斥了 f[

i]=∑

totj

=i+1

f[j]

∗cj−

itot

−if [i

]=∑j

=i+1

totf

[j]∗

ctot

−ij−

i注意後面的組合數,這個我想了很久

一開始我以為可以直接減,發現錯了。。

因為剩下這j−

i j−i

的數,也是要排列組合看一看的

code:

#include

#include

#include

#include

#include

using namespace std;

typedef long long ll;

const ll mod=1e9+7;

const ll max=(1

<<30);

const ll n=45;

ll n,m;

ll tot,tot1;//有多少good點 有多少個bad點

ll val[n];

ll ooo;

pair a[1048580];

int cnt[1048580][21];//點i個方案,選了j個點的有多少個

ll h[n];//有多少種選法,使得選出來i個great點是合法的

void dfs (ll x,ll y,ll a,ll b)//現在選了多少個了,值是多少

dfs(x+1,y,a,b);

if (b+val[x]<=m) dfs(x+1,y,a+1,b+val[x]);

}void dfs2 (ll x,ll y,ll a,ll b)

dfs2(x+1,y,a,b);

if (b+val[x]<=m) dfs2(x+1,y,a+1,b+val[x]);

}ll g[n],f[n];//至少有i個不是great點 剛好有i個不是great點

ll c[n][n];//行列式

ll gauss (ll x)//前i個good點只能連bad點

*/ ll ans=1;//被翻轉了多少次

for (ll u=1;uif (c[u][u]==0)

for (ll u=1;ufor (ll i=u+1;iwhile (c[i][u]!=0)

ans=-ans;}}

for (ll u=1;u*c[u][u]%mod;

/* printf("ans:%lld\n",ans);

system("pause");*/

ans=(ans+mod)%mod;

return ans;

}ll jc[n],inv[n];

ll c (ll x,ll y)

ll pow (ll x,ll y)

void dp ()

}}int main()

sort(val+1,val+1+n);

dp();

/*for (int u=0;u<=tot;u++) printf("%lld ",f[u]);

printf("\n");

for (int u=0;u<=tot;u++) printf("%lld ",g[u]);

printf("\n");*/

dfs(1,tot/2,0,0);

sort(a+1,a+1+ooo);

for (ll u=1;u<=ooo;u++)

dfs2(tot/2+1,tot,0,0);

ll ans=0;

for (ll u=0;u<=tot;u++) ans=ans+f[u]*h[tot-u]%mod;

printf("%lld\n",ans%mod);

}return

0;}

51Nod1446 限制價值樹

講課時候一點兒都沒懂 分成兩個部分 找到所有滿足sum mx的集合,即列舉哪些是great的 統計每個great的集合對應多少個樹 發現,第二個部分只和great集合大小有關 具體的第乙個部分 折半爆搜 sort 雙指標,得到g i 大小為i的great集合個數 第二部分 f i 表示欽定i個是gr...

51nod 1446 價值限制樹

51nod 1446 價值限制樹 真 一調一下午。題意 給 n 個點,每個點有權值 a i 若 a i 1 稱這個點 not good 否則是 good 的。形成任意一棵生成樹後若 good 的點相鄰的點有 good 點,則稱該點是 great 的。生成樹的價值是所有 great 的點的權值和。給定...

51Nod 1296 有限制的排列

acm模版 個人感覺,這個應該算是數字 dp。先通過處理輸入資料獲取乙個 state,表示每相鄰兩項之間的大小關係,state i 0,表示無特別關係,state i 1 表示第 i 項小於第 i 1 項,state i 2 表示第 i 項大於第 i 1 項。接著搞乙個 dp i j 表示由前 i ...