已知組合數(從\(n\)個物品中選擇\(m\)個物品的方案數)
\[c^m_n=c(n,m)=\binom=\frac
\]其中
\[n! = 1 \times 2 \times 3 \times \cdots \times n
\]\(specially\),\(define 0!=1\)
給定\(n\),\(m\),\(k\),對於所有的\(0 \le i \le n\),\(0 \le j \le min(i,m)\),有多少對\((i,j)\)滿足\(k \mid \)
求\[\sum_^n \sum_^ [k \mid c_i^j]
\]這個求和的方式就非常清晰了。那麼我們現在只用關係一下幾個問題:
看到\(n\),\(m\)最大只有\(2\times10^3\),但是\(t \le 10^4\),不難想到打表。
那麼怎麼遞推地求\(c_i^j\)呢?組合數有乙個重要的性質:
\[c_n^m=c_^m+c_^
\]可以從兩個方面給出解釋:
感性理解
從\(n\)個物品中拿出\(m\)個物品的方案數,相當於從\(n-1\)個物品中拿出\(m-1\)個物品(第\(n\)個物品不拿)的方案數+從\(n-1\)個物品中拿出\(m\)個物品(拿上第\(n\)個)的方案數
理性推導
\[\begin
c_^+c_^&=\frac + \frac\\
&=(n-1)! \times \frac\\
&=\frac\\
&=c^m_n
\end
\]時間上可以過去了,但是組合數會爆\(\texttt\)啊!
這個也很簡單解決
因為k是不變的,利用取模運算的加法原理,即\((a \% p+b\%p)\%p=(a+b)\%\),我們可以知道,我們想要知道的僅僅是這個數模\(k\)剩多少,用餘數遞推也是可以的。
最後用二位字首和儲存乙個區間內可以將\(k\)整除的組合數的個數即可。
#include#include#include#include#include#include#include#include#include#define il inline
#define re register
#define ll long long
#define ull unsigned long long
#define re register
#define debug printf("now is %d\n",__line__);
using namespace std;
templateinline void read(t&x)
}inline int read()
return x;
}int g[55];
templateinline void write(t x)
while(x);
for(re int i=g;i>=1;--i)putchar('0'+g[i]);putchar('\n');
}int t,k;
ll c[2010][2010],s[2010][2010];
void pre()
for(int i=1;i<=2000;i++)
s[i][i+1]=s[i][i]; }}
int main()
{ t=read();
k=read();
pre();
while(t--)
{ int i=read();
int j=read();
cout《注意組合數上下兩個字母的含義,不要寫反了。
洛谷P2822 組合數問題
題目描述 組合數 cmn m在上,n在下 表示的是從 n個物品中選出 m 個物品的方案數。舉個例子,從 1,2,3 三個物品中選擇兩個物品可以有 1,2 1,3 2,3 這三種選擇方法。根據組合數的定義,我們可以給出計算組合數 cmn的一般公式 其中 n 1 2 n 特別地,定義 0 1。小蔥想知道...
洛谷P2822 組合數問題(題解)
題目傳送 先了解一下有關組合數的公式 m在上,n在下 發現組合數的遞推的直觀影象形式就是楊輝三角 第i行第j列的數等於c i 1,j 1 由於題目要求多組組合數,便可以遞推組合數做預處理 直接用通項公式算什麼的太粗暴 慢 了 一看資料範圍,保證讓普通範圍溢位的節奏啊,但定心一看,我們只用知道每個組合...
P2822 組合數問題
題目描述 組合數c n mc n m 表示的是從n個物品中選出m個物品的方案數。舉個例子,從 1,2,3 三個物品中選擇兩個物品可以有 1,2 1,3 2,3 這三種選擇方法。根據組合數的定 義,我們可以給出計算組合數的一般公式 c n m m n m n 其中n 1 2 n 不清楚不要怪我,暫時找...