這個問題的核心在於,我們需要把「加入乙個球、拿出乙個球」這兩個操作轉化一下
因為顯然兩個操作同時進行的話,我們沒有辦法從單純的組合意義去分析
我們首先把$m$個球拿出來,表示全部都選拿走球
然後對於我們選定的加入球的操作,我們一次性加入兩個球
這樣問題就變成了乙個單純加入球的問題了
現在的問題是這樣的:
給定$n-m$個球,你有$m$次機會,每次可以加入兩個球,最後你會拿出$k$個球,問總方案數
我們把$k$個球的**分開考慮
假設$k$個裡面有$i$個來自於原來的$n-m$個球,$k-i$個來自於新加入的球
那麼選出$i$個的方案數應該為$c^i_$
後面新加入的球,我們考慮乙個遞推:$f[i][j]$表示從$i$對球中拿了東西,一共取出來了$j$個
那麼新加入一對球,可以選擇拿乙個或者拿兩個,因此可以寫出方程
$g[i][j]=f[i-1][j-2]+f[i-1][j-1]*2$
這個方程得到之後就好辦了
我們先列舉$k$個裡面從原來球中選出的個數,再列舉剩下的$k-i$用了多少對球($j$)
然後除了上面的兩個東西要乘起來之外,還要再乘以$c_j$和$2$,分別表示選出$j$對的方案,以及剩下的沒有取出的東西做出的貢獻
式子如下:
$ans = \sum_^k \sum_ }^ c(n-m,i) \ast c(m,j) \ast 2^ \ast f[k-i][j]$
這裡面的組合數每次詢問單獨處理,$f$陣列可以預處理好,總複雜度$o(tk^2)$
#include#include#include#include#include#define ll long long
#define mod 1000000007
using namespace std;
ll n,m,k,f[1010][1010],suf[510],suff[510],pre[510],c[510],cc[510],pw[510];
ll qpow(ll a,ll b)
return re;
}void init(ll p,ll q)
void getf() }}
int main()
(ans+=tmp*c[i]%mod)%=mod;
} printf("%lld\n",ans);
}}
遞推 傳球遊戲
時間限制 1 sec 記憶體限制 128 mb 上體育課的時候,小蠻的老師經常帶著同學們一起做遊戲。這次,老師帶著同學們一起做傳球遊戲。遊戲規則是這樣的 n個同學站成乙個圓圈,其中的乙個同學手裡拿著乙個球,當老師吹哨子時開始傳球,每個同學可以把球傳給自己左右的兩個同學中的乙個 左右任意 當老師再次吹...
goj1008 遞推 組合
這道題與以往的遞迴不太一樣,首先遞迴式子包括組合數,基本第歸式是c m,nf n f n 為n個人的全錯排,全錯排可以理解為所有的排列,然後減去反面的情況。即,乙個人排對的情況,兩個人排對的地方.全排對的情況.這個可以用公式c n,m right n m m取1.n 遞迴得出。然後遞迴的函式也與以前...
AYOJ 傳球遊戲 遞推
上體育課的時候,小蠻的老師經常帶著同學們一起做遊戲。這次,老師帶著同學們一起做傳球遊戲。遊戲規則是這樣的 n個同學站成乙個圓圈,其中的乙個同學手裡拿著乙個球,當老師吹哨子時開始傳球,每個同學可以把球傳給自己左右的兩個同學中的乙個 左右任意 當老師再次吹哨子時,傳球停止,此時,拿著球沒傳出去的那個同學...