【洛谷 2822】组合数问题 组合数、杨辉三角、前缀和。

——90%—

  杨辉三角递推

#include <cstdio>
#include <algorithm>

const int MAXN = 2007;

int n, m, t, k, f[MAXN][MAXN], sum[MAXN][MAXN];

void fs() {
    for (int i = 0; i < MAXN; i++) f[i][0] = 1;					// 注意初始化 

    for (int i = 1; i < MAXN; i++)
        for (int j = 1; j < MAXN; j++)
            f[i][j] = (f[i - 1][j] + f[i - 1][j - 1]) % k;
}

int main() {
    scanf("%d%d", &t, &k);
    
    fs();
//	
//	for(int i = 0; i < 10; i++) {
//		for (int j = 0; j < 10; j++) printf("%d ", f[i][j]);
//		printf("\n");	
//	}
        
    while (t--) {
        int ans = 0;
        scanf("%d%d", &n, &m);
        
        for (int i = 0; i <= n; i++) 
            for (int j = 0; j <= std::min(i, m); j++) 
                if (f[i][j] == 0) ans++;
        
        printf("%d\n", ans);
    }
    
    return 0;
}

 

—100%—

 二维前缀和优化。

#include <cstdio>

const int MAXN = 2000 + 7;

int T, k, n, m, c[MAXN][MAXN], s[MAXN][MAXN];

void get() {
	for (int i = 0; i <= 2000; i++)
		for (int j = 0; j <= i; j++) {
			if (!j && !i) c[i][j] = 1 % k;
			else c[i][j] = (c[i - 1][j] +c[i - 1][j - 1]) % k;
		}
}

void gets() {
	if (!c[0][0]) s[0][0] = 1;
	for (int i = 0; i <= 2000; i++) {
		for (int j = 0; j <= i; j++) {
			if (!i && !j) continue;
			else {
				if ((!i && j) || i == j) {							// 特殊处理处理边界情况 
					s[i][j] = s[i][j - 1];
					if (!c[i][j]) s[i][j]++;
				} else if (i && !j) {
					s[i][j] = s[i - 1][j];
					if (!c[i][j]) s[i][j]++;
				} else {
					s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1];
					if (!c[i][j]) s[i][j]++;
				}
			}
		}
	}
}

int main() {
	scanf("%d%d", &T, &k);
	
	get();
	
	gets();
	
	while (T--) {
		scanf("%d%d", &n, &m);
		printf("%d\n", s[n][m > n ? n : m]); 
	}
	return 0;
}

 

posted @ 2017-11-06 21:28  E-Valley  阅读(221)  评论(0)    收藏  举报