2014“华为杯”苏、鲁高校大学生程序设计大赛选拔赛暨东南大学第十届程序设计竞赛复赛【Difference Equation】

题目描述:
解N维递推方程,满足:
f(X1,X2,X3,⋯,Xn)=f(X1−1,X2,X3,⋯,Xn)+f(X1,X2−1,X3,⋯,Xn)+f(X1,X2,X3−1,⋯,Xn)+⋯+f(X1,X2,X3,⋯,Xn−1),(∀Xi>=0)∧(∃Xi>0)
f(0,0,0,⋯,0)=1,
f(X1,X2,X3,⋯,Xn)=0,∃Xi<0;

输入:
第一行一个整数T,表示有T组测试数据。
每组测试数据2行,第一行一个整数N。第二行有N个整数,表示X1...Xn。 1≤Xi≤50,1≤N≤50,1≤T≤100都是整数。

输出:
每组数据输出一行,只有一个整数,f(X1,X2...Xn)。最后的答案对10^9+7取余输出。

样例输入:
4
1
8
2
1 2
3
1 1 1
10
10 10 10 10 10 10 10 10 10 10

样例输出:
1
3
6
453209373

问题分析:
先分析二维的情况
即:f(x,y) = f(x-1,y)+f(x,y-1);
该函数可抽象为下图的二维空间的,从左上角的起点至右下角只能向x或y方向走的路径总数,易知存在左上角至任意一点的路径数为该点上方的路径种数和该点左方的路径种数。

2014“华为杯”苏、鲁高校大学生程序设计大赛选拔赛暨东南大学第十届程序设计竞赛复赛【Difference Equation】_第1张图片
二维空间

故:问题转化为求起点至某点按照上述走法的路径总数。
又由图可知每一条路径由x方向走4步,y方向走4步的排列组合
即:f(x,y) = C(x,x+y)*C(y,y);或f(x,y) = C(y,x+y)*C(x,x);
推而广之:n维空间即
f(x1,x2,x3,x4……xn) = C(x1,sum)*C(x2,sum-x1)*C(x3,sum-x1-x2)*……*C(xn,xn);
(sum为x1至xn的和)。

**

还是要吐槽下的markdown编辑不支持本地图片上传
java实现如下:

**


import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static BigInteger MOD = new BigInteger("1000000007");
public static BigInteger c(long num,long sum) {
BigInteger s=BigInteger.ONE;
num=num>sum-num?sum-num:num;
for(int i=1;i<=num;i++)
s = s.multiply(new BigInteger(String.valueOf(sum-i+1)));
for(int i=1;i<=num;i++)
s = s.divide(new BigInteger(String.valueOf(i)));
s = s.mod(MOD);
return s;
}
public static long count(long[] arr,long sum) {
BigInteger s=c(arr[0],sum);
for(int i=1,len=arr.length-1;i<=len;i++){
s = s.multiply(c(arr[i],sum-=arr[i-1]));
s = s.mod(MOD);
}
return Long.parseLong(s.toString());
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for(int i=0;i < t;i++){
int n = sc.nextInt();
long[] arr = new long[n];
long sum = 0l;
for(int j=0;j < n;j++){
arr[j] = sc.nextLong();
sum+=arr[j];
}
Arrays.sort(arr);
System.out.println(count(arr,sum));
}
}
}

你可能感兴趣的:(2014“华为杯”苏、鲁高校大学生程序设计大赛选拔赛暨东南大学第十届程序设计竞赛复赛【Difference Equation】)