链接:https://www.nowcoder.com/acm/contest/212/D
来源:牛客网
题目描述
清教需要定期给Index清除记忆,在此之前需要把当中的十万三千本禁书取出来......
不幸的是,禁书一旦离开了Index就非常脆弱,具体来说,每一本禁书都有一个魔力值 ai ,其记载的内容是 bi ,取出后的 n 本不同的禁书形成了一个排列,如果说对于一本禁书 i ,其左边存在一本不弱于它的魔力值的禁书 j ,禁书 i 就会因为禁书 j 的影响而消失。求对于所有可能的禁书排列,能保留下来的记载内容的种类数之和。由于答案可能很大,只需要输出对 998244353 取膜后的结果即可。
输入描述:
第一行一个数 n。 接下来 n 行,第 i 行两个整数 ai, bi ,表示第 i 本禁书的魔力值和记载内容。
输出描述:
输出共一个数,表示答案。
题解:
一本书会失效, 那么大于等于他魔法值的全在他后面,这样的情况是所有情况 * 1 / 大于等于他的数量。
为什么?证明: 小于他魔法值的忽略不看,情况就是剩余元素中他排最前面的情况数, 概率是 1 / 数量。
假如种类不会重复, 直接这么算贡献即可。
现在要去重, 把所有种类相同的书放在同一个vector 里面,按魔法值从小到大排序。
然后对于当前魔法值,他能产生贡献必须是他前面的书没有产生贡献的情况里面选,我们只需用总情况减去前面产生贡献了的情况,然后再乘概率即可。
代码:
#include <bits/stdc++.h>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif
#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pii;
const int MOD = 998244353 ;
const double PI = acos (-1.);
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 5e5 + 5;
map<int, vector<int> > v;
int a[MAXN], b[MAXN];
ll fastpow (int a, int n) {
ll ret = 1, base = a;
while(n) {
if (n & 1) ret = ret * base % MOD;
base = base * base % MOD;
n >>= 1;
}
return ret;
}
ll fac[MAXN];
int main() {
#ifdef LOCAL
freopen ("input.txt", "r", stdin);
#endif
int n;
scanf ("%d", &n);
fac[0] = 1;
for (int i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % MOD;
vector<int> all;
for (int i = 1; i <= n; i++) {
scanf ("%d %d", &a[i], &b[i]);
v[b[i]].pb (a[i]);
all.pb(a[i]);
}
sort(all.begin(), all.end());
ll ans = 0;
for (auto p : v) {
sort(p.second.begin(), p.second.end());
vector<int> & ar = p.second;
ll pre = 0;
int cnt = 0, pn = -1;
for (int i = 0; i < ar.size(); i++) {
if (pn == ar[i]) cnt++;
else cnt = 0;
pn = ar[i];
int bigger = n - (lower_bound(all.begin(), all.end(), ar[i]) - all.begin()) - cnt;
// debug(bigger)
ll t = (fac[n] - pre + MOD) % MOD * fastpow(bigger, MOD - 2) % MOD;
pre = (pre + t) % MOD;
ans = (ans + t) % MOD;
}
}
printf ("%lld\n", ans);
return 0;
}