摆放小球
题目描述
给定 nn 个不同的元素和一个常数 kk,请问将这 nn 个不同的元素划分为 kk 个相同的盒子里有多少种方案(盒子不可为空)。
输入描述
输入第一行包含两个整数 n,kn,k,其含义如题所述。
1≤k≤n≤1031≤k≤n≤103。
输出描述
输出共 11 行,包含一个整数,表示答案。由于答案可能很大,请对 109+7109+7 取模
输入输出样例
示例 1
输入
3 2
输出
3
运行限制
-
最大运行时间:1s
-
最大运行内存: 128M
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class Main {
static int N =1010,id,mod=(int)1e9+7;// static double p[]=new double[N];
static long f[][]=new long[N][N];public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String g[]=br.readLine().split(" "); int n=Integer.parseInt(g[0]),k=Integer.parseInt(g[1]); //同样采用记忆化搜索 //与上一个题不同的是 每组的数不能为0 //c(n,k)=kc(n-1,k)+c(n-1,k-1) 也就是把第n个元素分配至k个组中任意一个加上第n个元素单独一组的情况 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { f[i][j]=-1; } } long res=calc(n,k); System.out.println(res); } static long calc(int n,int m) { if(m==0||n<m)return 0;//一定要加这句 if(m==0 || m==n)return 1; if(f[n][m]!=-1){ return f[n][m]%mod; } f[n][m]=(m*calc(n-1,m)%mod+calc(n-1,m-1)%mod)%mod; return f[n][m]%mod; }}
dp求解组合数
问题描述
输入两个正整数 a,ba,b。输出 CabCab 的结果。结果对 109+7109+7 取模。
输入格式
输入一行,包含两个正整数 a,ba,b。(0≤b≤3000,b≤a≤3000)(0≤b≤3000,b≤a≤3000)
输出格式
输出 CabCab 的结果。结果对 109+7109+7 取模。
样例输入
5 0
样例输出
1
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N =3010,id,mod=(int)1e9+7;
// static double p[]=new double[N];
static long f[][]=new long[N][N];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String g[]=br.readLine().split(" ");
int n=Integer.parseInt(g[0]),k=Integer.parseInt(g[1]);
for (int i = 0; i <= n; i++) {
f[i][0]=1;
}
for (int i = 1; i <= k; i++) {
for (int j = 1; j <= n; j++) {
f[j][i]=(f[j-1][i]+f[j-1][i-1])%mod;//我不选第i件和选第i件
}
}
System.out.println(f[n][k]%mod);
}
}
求解组合数2
题目描述
小 ee 在蓝桥云课里上数学课时走神了(小朋友们不要学),他在思考一个奇怪的问题:
有 qq 次询问,每次询问 CnmCnm,结果对 109+7109+7 取模。
输入格式
第一行一个整数 qq 表示询问次数 (1≤q≤105)(1≤q≤105)。
对于每次询问,两个整数表示 n,m(0≤m≤n≤107)n,m(0≤m≤n≤107)。
输出格式
对于每次询问,一个整数表示答案。
样例输入
3
3 2
11 7
5 4
样例输出
3
330
5
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Main {
static int N=10000010,mod=(int)(1e9)+7;
static long fac[]=new long[N];
static long inv[]=new long[N];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
//String g[]=br.readLine().split(" ");
int q=Integer.parseInt(br.readLine());
fac[0]=1;
for (int i = 1; i < N; i++) {
fac[i]=fac[i-1]*i%mod;
}
// m的逆元记为 m^-1
//(m+1)!^-1等于 m!^-1 * (m+1)^-1
//re
//((m+1)!^-1)%mod=(m!^-1) * (m+1)^-1 %mod
//也就是 ((m+1)!^-1) * (m+1) %mod = (m!^-1) %mod //存在除法不能直接取模 需要逆元
//注:一项一项的求逆元 时间复杂度太高
//故 inv(m+1) * (m+1) = inv(m)
inv[(int)(1e7)]=quickMi(fac[(int)(1e7)],mod-2);
inv[0]=1;//要初始化为1
for (int i = (int)(1e7)-1; i >= 1; i--) {
inv[i]=inv[i+1]*(i+1)%mod;
}
for (int i = 0; i < q; i++) {
String g[]=br.readLine().split(" ");
int n=Integer.parseInt(g[0]),m=Integer.parseInt(g[1]);
long res=c(n,m);
bw.write(res%mod+"\n");
}
bw.flush();
}
static long c(int n,int m){
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
static long quickMi(long a,int m){
long res=1;
while(m>0){
if((m&1)==1){
res=res*a%mod;
}
a=a*a%mod;
m=m>>1;
}
return res;
}
}