Random Ranking
Mier_Samuelle · · 题解
:::info[Statement]{open}
有
原题
:::
先将区间离散化,拆成若干个小区间
据此,可定义
需对每个
可用退背包进一步优化。发现每一次只是撤销了
具体地,记
现在要倒推,那么移一下项,变为
据此转移即可。统计答案是区间加的形式,可用差分优化,复杂度
实现上有个小问题,就是上式中
模拟赛把这题改成了取模,我懒得改回浮点数了,将就着看吧。
:::success[
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 150;
const int MOD = 1e9 + 9;
int l[MAXN], r[MAXN], c[MAXN], f[MAXN][MAXN], g[MAXN][MAXN], ans[MAXN][MAXN], inv[MAXN], invi[MAXN], n, tot;
int qpow(int x, int y){
int res = 1;
while (y){
if (y & 1){
res = res * x % MOD;
}
x = x * x % MOD;
y >>= 1;
}
return res;
}
int p(int i, int x){
if (l[i] >= x){
return 1;
}
if (r[i] <= x){
return 0;
}
return (r[i] - x) * inv[i] % MOD;
}
signed main(){
// freopen("q.in", "r", stdin);
// freopen("q.out", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++){
cin >> l[i] >> r[i];
c[++tot] = l[i];
c[++tot] = r[i];
inv[i] = qpow(r[i] - l[i], MOD - 2);
}
for (int i = 1; i <= n; i++){
invi[i] = qpow(i, MOD - 2);
}
sort(c + 1, c + tot + 1);
tot = unique(c + 1, c + tot + 1) - c - 1;
for (int i = 1; i <= n; i++){
int li = lower_bound(c + 1, c + tot + 1, l[i]) - c;
int ri = lower_bound(c + 1, c + tot + 1, r[i]) - c;
for (int j = li; j < ri; j++){
int lj = c[j], rj = c[j + 1];
for (int u = 0; u <= n; u++){
for (int v = 0; v <= n; v++){
f[u][v] = 0;
}
}
f[0][0] = 1;
for (int k = 1; k <= n; k++){
if (i == k){
continue;
}
for (int u = 0; u <= n; u++){
for (int v = 0; v <= n; v++){
g[u][v] = f[u][v];
f[u][v] = 0;
}
}
for (int u = 0; u <= k; u++){
for (int v = 0; v <= k; v++){
f[u][v] = (f[u][v] + g[u][v] * p(k, rj) % MOD) % MOD;
if (u >= 1){
f[u][v] = (f[u][v] + g[u - 1][v] * (1 - p(k, lj) + MOD) % MOD) % MOD;
}
if (v >= 1){
f[u][v] = (f[u][v] + g[u][v - 1] * (p(k, lj) - p(k, rj) + MOD) % MOD) % MOD;
}
}
}
}
for (int u = 0; u < n; u++){
for (int v = 0; v < n; v++){
for (int k = u + 1; k <= min(u + v + 1, n); k++){
ans[i][k] = (ans[i][k] + (rj - lj) * inv[i] % MOD * f[u][v] % MOD * invi[v + 1] % MOD) % MOD;
}
}
}
}
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
cout << ans[i][j] << " ";
}
cout << "\n";
}
return 0;
}
:::
:::success[
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 400;
const int MOD = 1e9 + 9;
int l[MAXN], r[MAXN], c[MAXN], f[MAXN][MAXN], g[MAXN][MAXN], ans[MAXN][MAXN], inv[MAXN], invi[MAXN], n, tot;
int qpow(int x, int y){
int res = 1;
while (y){
if (y & 1){
res = res * x % MOD;
}
x = x * x % MOD;
y >>= 1;
}
return res;
}
int p(int i, int x){
if (l[i] >= x){
return 1;
}
if (r[i] <= x){
return 0;
}
return (r[i] - x) * inv[i] % MOD;
}
signed main(){
// freopen("q.in", "r", stdin);
// freopen("q.out", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++){
cin >> l[i] >> r[i];
c[++tot] = l[i];
c[++tot] = r[i];
inv[i] = qpow(r[i] - l[i], MOD - 2);
}
for (int i = 1; i <= n; i++){
invi[i] = qpow(i, MOD - 2);
}
sort(c + 1, c + tot + 1);
tot = unique(c + 1, c + tot + 1) - c - 1;
for (int i = 1; i < tot; i++){
int lj = c[i], rj = c[i + 1];
vector <int> act;
int cntl = 0;
for (int j = 1; j <= n; j++){
if (r[j] <= lj){
cntl++;
}
if (l[j] <= lj && r[j] >= rj){
act.push_back(j);
}
}
int len = (int)act.size();
if (!len){
continue;
}
for (int u = 0; u <= len; u++){
for (int v = 0; v <= len; v++){
f[u][v] = 0;
}
}
f[0][0] = 1;
for (int k = 0; k < len; k++){
int j = act[k];
for (int u = 0; u <= len; u++){
for (int v = 0; v <= len; v++){
g[u][v] = f[u][v];
f[u][v] = 0;
}
}
for (int u = 0; u <= k + 1; u++){
for (int v = 0; v <= k + 1; v++){
f[u][v] = (f[u][v] + g[u][v] * p(j, rj) % MOD) % MOD;
if (u >= 1){
f[u][v] = (f[u][v] + g[u - 1][v] * ((1 - p(j, lj) + MOD) % MOD) % MOD) % MOD;
}
if (v >= 1){
f[u][v] = (f[u][v] + g[u][v - 1] * ((p(j, lj) - p(j, rj) + MOD) % MOD) % MOD) % MOD;
}
}
}
}
for (int j : act){
for (int u = 0; u <= len; u++){
for (int v = 0; v <= len; v++){
g[u][v] = 0;
}
}
int pm = qpow((p(j, lj) - p(j, rj) + MOD) % MOD, MOD - 2);
for (int u = 0; u < len; u++){
for (int v = len - 1; v >= 0; v--){
g[u][v] = f[u][v + 1];
g[u][v] = (g[u][v] - g[u][v + 1] * p(j, rj) % MOD + MOD) % MOD;
if (u >= 1){
g[u][v] = (g[u][v] - g[u - 1][v + 1] * ((1 - p(j, lj) + MOD) % MOD) % MOD + MOD) % MOD;
}
g[u][v] = g[u][v] * pm % MOD;
}
}
for (int u = 0; u < len; u++){
for (int v = 0; v < len; v++){
int li = cntl + u + 1, ri = min(cntl + u + v + 1, n);
int val = (rj - lj) * inv[j] % MOD * g[u][v] % MOD * invi[v + 1] % MOD;
if (li <= ri){
ans[j][ri + 1] = (ans[j][ri + 1] - val + MOD) % MOD;
ans[j][li] = (ans[j][li] + val) % MOD;
}
}
}
}
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
ans[i][j] = (ans[i][j] + ans[i][j - 1]) % MOD;
cout << ans[i][j] << " ";
}
cout << "\n";
}
return 0;
}
:::