分析
首先给了我们n个题目,每个题目都有一个等级,现在要求从k个等级中分别选出一道题,问方案数
我们可以想到,去统计每个等级中题目的个数,然后方案数为从所有等级中任选k个等级,并从每个选中的等级中选一道题。
假设最终有n个等级,则最终答案为n个数中任意k个数的乘积
如果
k
=
1
k=1
k=1,我们会发现方案数是所有等级中题目数量之和
如果
k
=
3
k=3
k=3,我们有:
∑
i
=
1
n
∑
j
=
i
+
1
n
∑
k
=
j
+
1
n
a
[
i
]
∗
a
[
j
]
∗
a
[
k
]
\sum_{i=1}^{n}\sum_{j=i+1}^{n}\sum_{k=j+1}^{n}a[i]*a[j]*a[k]
∑i=1n∑j=i+1n∑k=j+1na[i]∗a[j]∗a[k]
∑
i
=
1
n
a
[
i
]
∑
j
=
i
+
1
n
a
[
j
]
∑
k
=
j
+
1
n
a
[
k
]
\sum_{i=1}^{n}a[i]\sum_{j=i+1}^{n}a[j]\sum_{k=j+1}^{n}a[k]
∑i=1na[i]∑j=i+1na[j]∑k=j+1na[k]
我们令 A [ x ] = ∑ i = x n a [ i ] A[x]=\sum_{i=x}^{n}a[i] A[x]=∑i=xna[i]
∑ i = 1 n a [ i ] ∑ j = i + 1 n a [ j ] A [ j + 1 ] \sum_{i=1}^{n}a[i]\sum_{j=i+1}^{n}a[j]A[j+1] ∑i=1na[i]∑j=i+1na[j]A[j+1]
我们令 B [ x ] = ∑ i = x n a [ i ] A [ i + 1 ] B[x]=\sum_{i=x}^{n}a[i]A[i+1] B[x]=∑i=xna[i]A[i+1]
∑ i = 1 n a [ i ] B [ i + 1 ] \sum_{i=1}^{n}a[i]B[i+1] ∑i=1na[i]B[i+1]
我们令 C [ x ] = ∑ i = x n a [ i ] B [ i + 1 ] C[x]=\sum_{i=x}^{n}a[i]B[i+1] C[x]=∑i=xna[i]B[i+1]
最后我们发现答案为: C [ 1 ] C[1] C[1]
所以,n个数中任意k个之积:
相当于上面的推导进行k次,也就是进行k次前缀和
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T>
void out(T x) { cout << x << endl; }
ll fast_pow(ll a, ll b, ll p) {ll c = 1; while(b) { if(b & 1) c = c * a % p; a = a * a % p; b >>= 1;} return c;}
ll exgcd(ll a, ll b, ll &x, ll &y) { if(!b) {x = 1; y = 0; return a; } ll gcd = exgcd(b, a % b, y, x); y-= a / b * x; return gcd; }
const int N = 1000 + 6;
const int mod = 998244353;
ll a[N];
ll sum[N], num[N];
int main()
{
ios::sync_with_stdio(false);
memset(sum, 0, sizeof(sum));
memset(num, 0, sizeof(num));
memset(a,0,sizeof(a));
map <int, int> q;
int n, k;
cin >> n >> k;
q.clear();
int cnt=0;
for(int i=1;i<=n;i++)
{
int x;
cin >> x;
if(q[x]==0)
{
q[x]=++cnt;
}
a[q[x]]++;
}
n = cnt;
for(int dk = 1; dk <= k; dk ++)
{
for(int i = n; i >= 1; i --)
{
sum[i] = (sum[i + 1] + (dk == 1 ? a[i] : a[i] * num[i + 1] % mod) % mod + mod) % mod;
}
for(int i = 1; i <= n; i ++)
num[i] = sum[i];
}
cout << sum[1] << endl;
}