對於求組合數,要根據所給資料範圍來選擇合適的演算法
這道題中所給的資料範圍適合用打表的方法直接暴力求解
先用4e6的複雜度預處理出所有的情況,再用1e4的複雜度完成詢問即可
#include
using
namespace std;
const
int n =
2010
;const
int mod =
1e9+7;
int c[n]
[n];
void
init()
}}intmain()
return0;
}
對於這道題的資料範圍,直接給出二維陣列大表就不太合適了
我們需要在這裡預處理出所有的階乘和階乘的逆元
運用組合數公式求解
這裡處理逆元是因為我們需要把除法轉化為乘法(具體內容可以看之前寫過的)
#include
using
namespace std;
typedef
long
long ll;
const
int n =
1e5+
10, mod =
1e9+7;
int fact[n]
;//預處理出所有的階乘
int infact[n]
;//預處理出所有階乘的逆元
intquickmod
(int a,
int k,
int p)
return res;
}void
init()
}int
main()
return0;
}
這裡給定的資料範圍更大,引入乙個定理來解決
盧卡斯定理:
在這裡只需要運用這個定理即可
在數學知識中,除乙個數一定要注意使用乘逆元的形式,保證不會出現取捨問題
#include
using
namespace std;
typedef
long
long ll;
intquickmod
(int a,
int k,
int p)
return res;
}intc(
int a,
int b,
int p)
return res;
}int
lucas
(ll a, ll b,
int p)
intmain()
return0;
}
這裡可以利用組合數公式求解
如果要直接用高精度的話需要寫乙個乘法乙個除法比較麻煩
所以可以先進行因式分解,將答案分解成因式相乘的形式在利用高精度相乘進行解決
#include
using
namespace std;
const
int n =
5010
;int primes[n]
, cnt;
int sum[n]
;bool st[n]
;void
get_primes
(int n)}}
intget
(int n,
int p)
//分解質因數,求n這個數中有多少個p
return res;
}vector<
int>
mul(vector<
int> a,
int b)
while
(t)return c;
}int
main()
這個題用到了卡特蘭數
將這個題目中的01序列抽象在乙個座標系中,0表示向右,1表示向上
因此題目中的字首條件即表示所走的每一步都要在y=x這條直線的一側即可
這種做法即是用卡特蘭數來進行解決的
#include
using
namespace std;
typedef
long
long ll;
const
int mod =
1e9+7;
intquickmod
(int a,
int k,
int p)
return res;
}int
main()
吉首 組合數 求組合數因子個數
時間限制 1 sec 記憶體限制 128 mb 求組合數c n,m 以及c n,m 因子個數。n和m,其中0 m n 50,以eof結束。該組合數結果。3 2 4 23 2 6 4先利用楊輝三角求出組合數,然後就是求出因子數了 求因子數 素數分解的唯一性,乙個數可以被分解成若干素數相乘 p1 x1 ...
組合數學筆記
從n個數中選m個數,每個數至多選一次,方案數 性質 c n,0 c n,n 1 c n,m c n,n m c n,m c n 1,m 1 c n 1,m 楊輝三角 二項式展開 x y n i 0.n c n,i x iy n i 那這裡先說一下楊輝三角 前提 每行端點與結尾的數為1 每個數等於它上...
SPOJ INTSUB 組合數學
題目鏈結 題意 給你乙個集合,問有多少個子集是有趣的。有趣的集合定義是,集合中兩個不一樣的數,其中a是集合裡的最小值,b是a的倍數。題解 對於數字a,集合中存在x 2n a 1個大於a的倍數,也存在y 2n x a個大於a但不是a的倍數的數。對於有趣的集合必須要出席那大於a的倍數,一共有2 x 1種...