设为首页 加入收藏

TOP

UVA 10910 Marks Distribution(组合数学 或 递推)
2015-07-20 17:29:18 来源: 作者: 【 】 浏览:2
Tags:UVA 10910 Marks Distribution 组合 数学 递推

Marks Distribution

Time limit: 3.000 seconds

In an examination one student appeared in N subjects and has got total T marks. He has passed in all the Nsubjects where minimum mark for passing in each subject is P. You have to calculate the number of ways the student can get the marks. For example, if N=3, T=34 and P=10 then the marks in the three subject could be as follows.

Subject 1

Subject 2

Subject 3

1

14

10

10

2

13

11

10

3

13

10

11

4

12

11

11

5

12

10

12

6

11

11

12

7

11

10

13

8

10

11

13

9

10

10

14

10

11

12

11

11

10

12

12

12

12

12

10

13

10

13

11

14

11

13

10

15

10

14

10

So there are 15 solutions. So F (3, 34, 10) = 15.

Input

In the first line of the input there will be a single positive integer K followed by K lines each containing a single test case. Each test case contains three positive integers denoting N, T and P respectively. The values of N, T and P will be at most 70. You may assume that the final answer will fit in a standard 32-bit integer.

Output

For each input, print in a line the value of F (N, T, P).

Sample Input

Output for Sample Input

2
3 34 10
3 34 10

15
15


题意:一个人N门课程的总成绩为T,每门课程的最低成绩为P,求一共有多少种可能的分配方法。

分析:

解法一:组合数学

这个问题可以转化为把m个物体放到n个盒子里面,允许有的盒子为空,问一共有多少种放置方法。因为除去每门课必须的P以后,剩下的M=T-N*P可以随意分配到N门课程里面。这样问题就变成了“插板法”的经典应用。分成N组需要N-1个隔板,再加上M个物体,可以看成N-1+M个空隙,然后从这些空隙中选出N-1用来放隔板,共有C(N-1+M,N-1)中种方法。

#include 
  
   
typedef long long LL;

LL C(LL n, LL k) {
    if(n - k < k) k = n - k;
    LL ans = 1;
    for(int i = 1; i <= k; i++)
        ans = ans * (n - i + 1) / i;
    return ans;
}

int main() {
    int cas;
    LL n, t, p;
    scanf("%d", &cas);
    while(cas--) {
        scanf("%lld%lld%lld", &n, &t, &p);
        t = t - n * p;
        LL ans = C(n + t - 1, n - 1);
        printf("%lld\n", ans);
    }
    return 0;
}
  

解法二:递推

用a[i][j]表示前i个盒子里面放了j个物体的放法,则a[i][j] = a[i-1][0] + a[i-1][1] + …… + a[i-1][j].

初始化dp[i][0] = 1。

#include 
  
   
#include 
   
     const int N = 72; typedef long long LL; LL a[N][N]; int main() { int T; LL n, p, t; scanf("%d", &T); while(T--) { scanf("%lld%lld%lld", &n, &t, &p); t = t - n * p; memset(a, 0, sizeof(a)); for(int i = 0; i <= n; i++) a[i][0] = 1; for(int i = 1; i <= n; i++) { for(int j = 1; j <= t; j++) { for(int k = 0; k <= j; k++) a[i][j] += a[i-1][k]; } } printf("%lld\n", a[n][t]); } return 0; }
   
  



】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇POJ2456 Aggressive cows(二分+贪.. 下一篇HDOJ 2024 C语言合法标识符

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·About - Redis (2025-12-26 08:20:56)
·Redis: A Comprehens (2025-12-26 08:20:53)
·Redis - The Real-ti (2025-12-26 08:20:50)
·Bash 脚本教程——Li (2025-12-26 07:53:35)
·实战篇!Linux shell (2025-12-26 07:53:32)