傳送門:
思路:首先把等於的縮成乙個點,由好的向壞的連邊,有環肯定無解。
然後題目裡說「小
d都最多隻記住了某一張質量不比
i差的另一張
ki」那就是每個點就最多只有一條入邊,那存在合法方案的圖就一定是森林。
加乙個虛根,這可以樹形dp了。
假設f[i][j]表示i號點的子樹中的所有點構成的有且只有j個小於號的序列的個數
那麼考慮怎麼合併兩個子樹的答案
假設現在的兩個兒子是x,y,子樹大小分別為siz[x],siz[y]
列舉兩個兒子的序列小於號個數i,j。
那麼合併出來的新序列小於號個數k就在max(i,j)到i+j之間。
那麼問題就是求對於k個盒子,有i個白球,j個黑球,求有多少種方案。
答案就是f[x][i]*f[y][j]*c[k][i]*c[i][j-(k-i)] c是組合數。
實現的時候,再開乙個g陣列,g[i]
就是之前的兒子的子樹的點構成的小於號為j個的序列方案數
注意兒子合併完後,因為新加了當前點,序列長度要+1
#include#include#include#includeconst int maxn=105,maxm=205,mod=(int)(1e9+7);typedef long long ll;
using namespace std;
int n,m,pre[maxm],now[maxn],son[maxm],tot,fa[maxn],cnt,deg[maxn],siz[maxn];char op[3];
ll c[maxn][maxn],f[maxn][maxn],ans,g[maxn];
bool bo[maxn];
struct nodeli[maxn];
void add(int a,int b)
int getfa(int x)
bool dfs(int x,int fa)
else
} if (x)
return 1;
}int main()
if (op[0]=='>') swap(x,y);
li[++cnt]=(node);
} for (int i=1;i<=cnt;i++)
for (int i=1;i<=n;i++) if (!deg[getfa(i)]) add(0,getfa(i));
if (!dfs(0,-1)) return puts("0"),0;
//for (int i=1;i<=n;i++) printf("%d %lld\n",i,f[0][i]);
for (int i=1;i<=siz[0];i++) ans=(ans+f[0][i])%mod;
printf("%lld\n",ans);
return 0;
}
BZOJ4013 HNOI2015 實驗比較
先並查集合並 因為所有的xi互不相同,所以合併完後應該是乙個森林,如果出現環就無解。我們新建乙個根連向所有入度為0的點,就變成了一棵樹,考慮樹形dp。因為只要兩點不是其中一點是另一點的祖先的關係,他們就可以劃 因為大小關係不確定,所以將 連線的看做一塊,f i j 表示以 i 為根的子樹分成了j塊 ...
BZOJ 4013 HNOI2015 實驗比較
樹dp 組合數 網上題解很多,這裡就放個有注釋的 code 1 include 2 include 3 include 4 include 5 include 6 include 7 define maxn 110 8 define mod 1000000007 9using namespace s...
4013 HNOI2015 實驗比較
time limit 5 sec memory limit 512 mb submit 535 solved 268 submit status discuss 小d n 張,編號為1 到 n。實驗分若干輪進行,在每輪實驗中,小 d會被要求 某兩張隨機選取的,然後小d 需要根據他自己主觀上的判斷確定...