1. 程式人生 > >[JZOJ5130][51nod1446][SDOI省隊集訓2017]蘋果樹

[JZOJ5130][51nod1446][SDOI省隊集訓2017]蘋果樹

題目描述

有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後的結果。

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

計數

注意點與點間沒有區別,權值可以另外再考慮。
我們考慮g[i]表示至少i個good點不是great點,假設一共有x個good點。
那麼這i個點只能向非good點連邊,而剩下的可以任意連。
然後用基爾霍夫矩陣做生成樹計數就是方案。
現在考慮設f[i]表示恰好i個good點不是great點,可以容斥計數。
f[i]=g[i]xj=i+1Cjixif[j]

權值

考慮處理出h[i]表示選擇i個good點使得權值和<=lim的方案。
考慮折半搜尋,排序後可以two-pointer。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++) #define fd(i,a,b) for(i=a;i>=b;i--) using namespace std; typedef long long ll; const int maxn=40+10,maxtot=1050000,mo=1000000007; struct dong{ int x,y; friend bool operator <(dong a,dong b){ return a.y<b.y; } } e1[maxtot],e2[maxtot]; int f[maxn],g[maxn],h[maxn]; int
d[maxn][maxn],a[maxn][maxn],c[maxn][maxn],cr[maxn][maxn],v[maxn],b[maxn]; int i,j,k,l,t,n,lim,m,x,top1,top2,ans,ca; void link(int x,int y){ a[x][y]++; a[y][x]++; d[x][x]++; d[y][y]++; } int qsm(int x,int y){ if (!y) return 1; int t=qsm(x,y/2); t=(ll)t*t%mo; if (y%2) t=(ll)t*x%mo; return t; } int det(){ int i,j,k,l,t=n-1,cnt=1; fo(i,1,t){ fo(j,i+1,t){ if (!c[j][i]) continue; l=(ll)c[i][i]*qsm(c[j][i],mo-2)%mo; fo(k,i,n) (c[i][k]-=(ll)c[j][k]*l%mo)%=mo; fo(k,i,n) swap(c[i][k],c[j][k]); cnt=-cnt; } if (!c[i][i]) return 0; cnt=(ll)cnt*c[i][i]%mo; } return cnt; } int calc(int y){ int i,j; fo(i,1,n) fo(j,1,n) d[i][j]=a[i][j]=c[i][j]=0; fo(i,1,y) fo(j,x+1,n) link(i,j); fo(i,y+1,n) fo(j,i+1,n) link(i,j); fo(i,1,n) fo(j,1,n) cr[i][j]=d[i][j]-a[i][j]; fo(i,1,n-1) fo(j,1,n-1) c[i][j]=cr[i+1][j+1]; return det(); } void dfs(int i,int y,int cnt,int f){ if (y>lim) return; if (!f&&i==x/2+1){ e1[++top1].x=cnt; e1[top1].y=y; return; } else if (f==1&&i==x+1){ e2[++top2].x=cnt; e2[top2].y=y; return; } dfs(i+1,y,cnt,f); dfs(i+1,y+v[i],cnt+1,f); } int main(){ //freopen("apple.in","r",stdin);freopen("apple.out","w",stdout); scanf("%d",&ca); while (ca--){ scanf("%d%d",&n,&lim); fo(i,1,n) scanf("%d",&v[i]); sort(v+1,v+n+1); reverse(v+1,v+n+1); x=0; fo(i,1,n) if (v[i]==-1) break;else x++; fo(i,0,x) g[i]=calc(i); fo(i,0,x) fo(j,0,x) c[i][j]=0; c[0][0]=1; fo(i,1,x){ c[i][0]=1; fo(j,1,i) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mo; } fd(i,x,0){ f[i]=g[i]; fo(j,i+1,x) (f[i]-=(ll)c[x-i][j-i]*f[j]%mo)%=mo; } reverse(f,f+x+1); top1=top2=0; dfs(1,0,0,0); dfs(x/2+1,0,0,1); sort(e1+1,e1+top1+1); sort(e2+1,e2+top2+1); fo(i,0,x) b[i]=h[i]=0; fo(i,1,top2) b[e2[i].x]++; j=top2; fo(i,1,top1){ while (j&&e1[i].y+e2[j].y>lim){ b[e2[j].x]--; j--; } fo(k,0,n-x/2) (h[e1[i].x+k]+=b[k])%=mo; } ans=0; fo(i,0,x) (ans+=(ll)f[i]*h[i]%mo)%=mo; (ans+=mo)%=mo; printf("%d\n",ans); } }

相關推薦

[JZOJ5130][51nod1446][SDOI集訓2017]蘋果樹

題目描述 有N個點(N<=40)標記為0,1,2,…N-1,每個點i有個價值val[i],如果val[i]=-1那麼這個點被定義為bad,否則如果val[i] >=0那麼這個點為定義為good。現在給這N個點間連上N-1條邊,使它們構成一個生成樹,

[JZOJ5133][SDOI集訓2017]重建

題目描述 傻逼題 預處理每個圖裡經過k條邊的最短路。 然後可以用單調棧求出一些關鍵的c值使得某副圖改變最短路經過的邊數。 接著順序掃這些關鍵點,解方程即可。 #include<cstdio> #include<algorith

[2018 FJ 集訓 Day6][校內訓練]傳統題(組合數學妙題)

Meaning 一個長度為 n n n 的序列,每個位置可以被染成

2018SD集訓R1 D3

T1 題解: 首先你可以寫一個n=L的暴力,這樣可以得到20pts Polya定理的應用。先來看Polya定理。 Polya定理:設 G = {a1,a2,…,ag}是 N 個物件的置換群,用 M 種顏色給這 N 個物件著色,則不同的著色 方案數為:

[2018HN集訓D1T3] Or

長度 turn const 完全 src return == for alt [2018HN省隊集訓D1T3] Or 題意 給定 \(n\) 和 \(k\), 求長度為 \(n\) 的滿足下列條件的數列的數量模 \(998244353\) 的值: 所有值在 \([1,2^

[2018HN集訓D8T3] 水果拼盤

char 分享 ans .cn 普通 參考 自帶 value tps [2018HN省隊集訓D8T3] 水果拼盤 題意 給定 \(n\) 個集合, 每個集合包含 \([1,m]\) 中的一些整數, 在這些集合中隨機選取 \(k\) 個集合, 求這 \(k\) 個集合的並集的

【歐拉回路+最小生成樹】SD開車@山東2018一輪集訓day1

目錄 【歐拉回路+最小生成樹】SD開車@山東2018省隊一輪集訓day1 PROBLEM 題目描述 輸入 輸出 樣例輸入 樣例輸出 提示 SOLUTION CODE

loj6029 「雅禮集訓 2017 Day1」市場

type string turn struct sta def for its loj 傳送門:https://loj.ac/problem/6029 【題解】 考慮如果有一些近似連續的段 比如 2 2 2 3 3 3,考慮在除3意義下,變成0 0 0 1 1 1,相當於整

「6月雅禮集訓 2017 Day7」電報

連通塊 print 要花 style view 最小 pre mes freopen 【題目大意】 有n個島嶼,第i個島嶼有有向發射站到第$p_i$個島嶼,改變到任意其他島嶼需要花費$c_i$的代價,求使得所有島嶼直接或間接聯通的最小代價。 $1 \leq n \leq 1

「6月雅禮集訓 2017 Day8」infection

div 線段 經典的 n) view sig iostream 技術 hid 【題目大意】 有$n$個人,每個人有一個初始位置$x_i$和一個速度$v_i$,你需要選擇若幹個人來感染一個傻逼病毒。 當兩個人相遇(可以是正面和背面),傻逼病毒會傳染,求經過無限大時間後,傳染完

「6月雅禮集訓 2017 Day11」tree

題目 -a stdio.h stdin amp pac out pan 樹形dp 【題目大意】 給出一棵帶權樹,有兩類點,一類黑點,一類白點。 求切斷黑點和白點間路徑的最小代價。 $n \leq 10^5$ 【題解】 直接最小割能過。。但是樹形dp明顯更好寫 設$f_{x,

湖南省集訓 -- 1

連續 三次 線段 什麽 導致 半平面 .com 數組 noi 不知道為什麽今天狀態 大 好 可能是暴力分比較簡單吧,來認真寫一下總結 開局睡了1h…… 然後考慮a題,發現特殊性:因為最後的和一定是10^n的,最後兩個數一定是後面一段全是0,前面一段兩個數的和是⑨,0和⑨中間

2741. [濟南集訓 2017] 掰巧克力

fault review 時間 name printf namespace ace 多少 stdout ★ 輸入文件:bpmp.in 輸出文件:bpmp.out 簡單對比 時間限制:1 s 內存限制:256 MB 【題目描述】 yyy收到了一塊

#6030. 【雅禮集訓 2017 Day1】矩陣

line 字符 oid inline 技術分享 任務 有一種 run -h #6030. 「雅禮集訓 2017 Day1」矩陣 題目描述 有一個 n×n 的矩

[六聯考2017]相逢是問候

多少 i++ ans 問題 不用 .... int out content 相逢是問候 2017-09-09 Description Informatikverbindetdichundmich. 信息將你我連結。B君希望以維護一個長度為n的數組,這個數組的下標為從1到

「長樂集訓 2017 Day10」劃分序列 (二分 dp)

color -html math != mes 序列 spa cto html 「長樂集訓 2017 Day10」劃分序列 題目描述 給定一個長度為 n nn 的序列 Ai A_iA?i??,現在要求把這個序列分成恰好 K KK 段,

cogs2745[濟南集訓 2017] 求gcd之和【解題報告】

text tar problem ace == clas ++ aps 解題報告 題目鏈接 題目大意: 給定n、m,求出(1--n)所有數與(1--m)所有數的gcd之和。 看完題解後可以發現一個有用的結論: 對於一個數,他的所有因子的歐拉值之和等於這個數本身。

清華集訓2017遊記

省選 訓練 0ms 經驗 狀態 操作 logs 上下 繼續 Day0 報到日 火車上膜了一發附中大佬 試機時感覺機房很熱,頭腦很不清醒 晚上和cjl,xjt一起吃火鍋,等了半天,感覺有毒 Day1 水落在酒店餐廳了,幸好賽場發水 賽前松爺在群裏發了一句GL & HF

「雅禮集訓 2017 Day5」矩陣

都是 答案 times class its 矩陣 light ron 所有 填坑填坑.. 感謝wwt耐心講解啊.. 如果要看這篇題解建議從上往下讀不要跳哦.. 30pts 把$A$和$C$看成$n$個$n$維向量,那$A_i$是否加入到$C_j$中就可以用$B_

bug運輸[遼寧2014年互測一]

如果 復雜 bsp 幹什麽 c++ gpo 題目 putchar 至少 奇奇怪怪的題目,不知道他要我們幹什麽。 我們觀察一波局勢,發現答案最大不過5.因為如果答案是6或以上的話,我們就至少要2^(5*5)個5*5的方格。 仔細計算一波時間復雜度,再信仰一波,堅信暴