程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> UVA 10910 Marks Distribution(組合數學 或 遞推)

UVA 10910 Marks Distribution(組合數學 或 遞推)

編輯:C++入門知識

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;
}



  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved