[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點,可以容斥計數。
權值
考慮處理出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的方格。 仔細計算一波時間復雜度,再信仰一波,堅信暴