「專題訓練」k-Tree(CodeForces Round #247 Div.2 C)
阿新 • • 發佈:2018-12-01
cout code names spa 題意 某個結點 增長 space force 個邊,因此對於一個K-Tree的某個點(每個點是等價的,所以決定性因素只能是和),如果它還剩\(n\)的權重和沒有走,那麽它的狀態轉移方程就是\(dp[n-1]+dp[n-2]+...+dp[n-k]=dp[n]\)。這樣就能求出沒有限制條件下的路徑個數。
然後考慮一下限制條件。不小於\(d\),很自然地會覺得有點困難去實現。於是想到正難則反,我們求出所有邊權重小於d的情況就行了——也就是\(k=d-1\)。而同樣的,不改變的是預先的權重和\(n\),因此再次運用上面的狀態轉移方程,然後把\(k\)代入為\(d-1\)即可。二者最後相減即可。
題意與分析(Codeforces-431C)
題意是這樣的:給出K-Tree——一個無限增長的樹,它的每個結點都恰有\(K\)個孩子,每個節點到它\(K\)個孩子的\(K\)條邊的權重各為\(1,2,...,K\),問現有多少條路徑,使從根節點出發到某個結點所經過的邊權重之和恰為n,且經過的邊至少有一條權重不小於\(d\)。
我們來考慮一下階段:一層一層的走下去——這個是顯然的。而狀態是什麽?影響我們答案(路徑條數)的只有一個,權重的和,它是由我們底下的若幹個孩子所走的權重和的情況的和構成的。從某個節點走到某個節點改變了什麽?當我走了一條邊i,我就還剩\(n-i\)的權重需要走了。而我有\(k\)
然後考慮一下限制條件。不小於\(d\),很自然地會覺得有點困難去實現。於是想到正難則反,我們求出所有邊權重小於d的情況就行了——也就是\(k=d-1\)。而同樣的,不改變的是預先的權重和\(n\),因此再次運用上面的狀態轉移方程,然後把\(k\)代入為\(d-1\)即可。二者最後相減即可。
代碼
註意減法操作時候的取模。
#include <bits/stdc++.h> using namespace std; const long long mod=1e9+7; long long dpa[105], dpb[105]; int main() { int n,k,d; cin>>n>>k>>d; dpa[0]=dpb[0]=1; for(int i=1;i<=n;++i) { for(int j=1; j<=k && i-j>=0; ++j) { dpa[i]=(dpa[i]+dpa[i-j])%mod; } } for(int i=1;i<=n;++i) { for(int j=1; j<=d-1 && i-j>=0; ++j) { dpb[i]=(dpb[i]+dpb[i-j])%mod; } } cout<<(dpa[n]-dpb[n]+mod)%mod<<endl; return 0; }
「專題訓練」k-Tree(CodeForces Round #247 Div.2 C)