又是一道非常水的绿题,真开心,hahaha……

题意解毒

好像没啥好解毒的,直接看思路吧

思路

直接暴力的话想都不用想,直接 T 飞。

我们可以先根据组合恒等式 $C_{n}^{m} = C_{n - 1}^{m - 1} + C_{n}^{m - 1}$ 递推求出所有组合数。因为 $k\mid C_{n}^{m}$ 就相当于 $C_{n}^{m} \equiv 0 \pmod {k}$ ,而且k 是一开始就给定的,这样我们就可以在算组合数的时候就边算边对 $k$ 取模。然后再判断有多少个的值是 $0$ 就行了

95pts Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e3 + 5;
int t, k, m, n, c[N][N];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> t >> k;
for (int i = 0; i <= 2e3; i++)
{
c[i][0] = c[i][i] = 1;
for (int j = 1; j < i; j++)
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % k;
}
while (t--)
{
int ans = 0;
cin >> n >> m;
for(int i = 0; i <= n; i++)
for(int j = 0; j <= min(i, m); j++)
ans += c[i][j] == 0;
cout << ans << "\n";
}
}

TLE 了?!

该算法时间复杂度是 $O(max(n)^2)$ ,算上查询倍数是 $O(tmax(n)^2)$,TLE 很正常吧。能得到 95pts 已经很不错了,说明数据太水了

正解

思考如何优化。
我们可以发现要求得的答案是一个区间中的 $0$ 的数量,所以可以很自然的想到用二维差分来优化查询效率。

AC Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e3 + 5;
int t, k, m, n, c[N][N], sum[N][N];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> t >> k;
for (int i = 0; i <= 2e3; i++)
{
c[i][0] = c[i][i] = 1;
for (int j = 1; j < i; j++)
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % k;
}
for (int i = 1; i <= 2e3; i++)
for (int j = 1; j <= 2e3; j++)
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + (c[i][j] == 0 && j <= i);
while (t--)
{
cin >> n >> m;
cout << sum[n][min(n, m)] << "\n";
}
}