题解:成绩排名

题目见正文

Posted by TH911 on May 24, 2025

数据包 洛谷自建题目

题目

题目描述

小 Z 毕业后去了 H 中学教书,他带的班级有 $n$ 个学生,对于每个学生 $i$ 可以用一个正整数 $A_i$ 来衡量其学习能力($i=1,2,3,\cdots,n$)。有一天,小 Z 捡到了 $k$ 本神奇教材,如果给一个学生学习了这本教材,他的学习能力就会变成原来的 $t$ 倍。小 Z 决定将这本书随机且等概率地发放给班上的 $n$ 个同学,每个学生最多只能得到一本书,也就是说班上会有 $k$ 名同学被分配到书,学习能力变成 $t$ 倍,而剩下 $n-k$ 名同学没有书, 学习能力不变。现在小 Z 想知道,在所有的分配方案中,对于班上的每个同学来说排名保持不变的情况分别有多少种。

在这里,排名是指学习能力比他高的人的数目加 $1$,比方说有 $5$ 个同学,学习能力为 $\langle3,2,2,1,1\rangle$,他们的排名即 $\langle1,2,2,4,4\rangle$。

输入格式

第一行输入 $3$ 个整数 $n,k,t$,分别代表学生的数目、神奇教材的数目以及学习能力翻的倍数。第二行输入 $n$ 个整数 ,代表每个学生的学习能力,编号从 $1$ 到 $n$。

输出格式

输出 $n$ 行,第 $i$ 行输出一个整数代表第 $i$ 位同学在 Z 老师发完书后学习能力排名保持不变的所有可能的情况数目。由于这些数可能非常大,请输出其对 $10^9+7$ 取模后的结果。

输入输出样例

输入 #1

1
2
4 2 2
1 2 3 4

输出 #1

1
2
3
4
4
3
2
4

说明/提示

对于 $10\%$ 的数据,有 $1\leq n\leq10$。

对于 $30\%$ 的数据,有 $1\leq n\leq10^3$。

对于另外 $10\%$ 的数据,有 $1\leq n\leq10^5$ 且 $k=1$。

对于 $100\%$ 的数据,有 $1\leq k\leq n\leq10^5,2\leq t\leq10^3,1\leq A_i\leq10^9$。

rankSample.zip

题解

设一个人的 $A$ 值为 $i$,考虑其答案。

记 $\vert >i\vert$ 表示所有 $A$ 值大于 $i$ 的人的个数。同理,有 $\vert \leq i\vert,\cdots$。

记 $\left\vert[l,r]\right\vert=\vert\geq l\vert-\vert\geq r+1\vert$ 表示所有 $A$ 值在 $[l,r]$ 中的人的个数。

分两类讨论:

  • $i$ 不会翻倍。

    因为其排名不变,$A$ 值大于 $i$ 的人翻倍显然不影响,这一部分人的数量为 $\vert>i\vert$。

    而对于 $\left\vert\leq\dfrac{i}{t}\right\vert$ 这一部分的人,其翻倍后的 $A$ 值仍然小于等于 $i$,不影响 $i$ 的排名。

    从这两部分的人中选择 $k$ 个即可,此部分答案为:

    \[\begin{pmatrix} \vert>i\vert+\left\vert\leq\dfrac it\right\vert\\ k \end{pmatrix}\]
  • $i$ 会翻倍。

    则 $i$ 的 $A$ 值会从 $i$ 变为 $ti$,则 $\vert[i+1,ti]\vert$ 这一部分的人必须都要翻倍,这样才能保证 $i$ 的排名不变。

    记 $pl=\vert[i+1,ti]\vert+1$ 表示必须翻倍的人数

    则只有当 $pl\leq k$ 的时候,才符合题意。

    • 对于 $\vert>ti\vert$ 这一部分人,随便翻倍都不影响 $i$ 的排名。
    • 对于 $\vert\leq i\vert-1$ 这一部分人,翻倍依然不影响 $i$ 的排名,因为其翻倍后小于等于 $ti$。(减一是为了去除当前讨论的 $i$,可能会存在多个 $A$ 值相等。)

    此部分的答案为:

    \[\binom{\vert>ti\vert+\vert\leq i\vert-1}{k-pl}\]

对于诸如 $\vert>i\vert$ 的求法,只需要排序后二分即可。

AC 代码

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
typedef long long ll;
constexpr const int N=1e5,P=1e9+7;
struct student{
	int a,id,ans;
}a[N+1];
int n,k,t,fact[N+1];
void C_pre(int n){
	fact[0]=1;
	for(int i=1;i<=n;i++){
		fact[i]=1ll*fact[i-1]*i%P;
	}
}
int qpow(int a,int n){
	int base=a,ans=1;
	while(n){
		if(n&1){
			ans=1ll*ans*base%P;
		}
		base=1ll*base*base%P;
		n>>=1;
	}
	return ans;
}
int C(int n,int m){
	if(n<m||m<0||n<0){
		return 0;
	}
	return 1ll*fact[n]*qpow(1ll*fact[m]*fact[n-m]%P,P-2)%P;
}
//≤x的数量 
int leq(ll x){
	int l=1,r=n+1;
	while(l<r){
		int mid=l+r>>1;
		if(a[mid].a>x){
			l=mid+1;
		}else{
			r=mid;
		}
	}
	return n-r+1;
}
//≥x的数量
int geq(ll x){
	return n-leq(x-1);
} 
int main(){
	/*freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);*/
	
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	cin>>n>>k>>t;
	C_pre(n);
	for(int i=1;i<=n;i++){
		cin>>a[i].a;
		a[i].id=i;
	}
	//单调不增 
	sort(a+1,a+n+1,[](student a,student b){
		return a.a>b.a;
	});
	for(int i=1;i<=n;i++){
		a[i].ans=C(geq(a[i].a+1)+leq(a[i].a/t),k);
		int pl=leq(1ll*a[i].a*t)-leq(a[i].a)+1;
		if(pl<=k){
			a[i].ans=(a[i].ans + C(geq(1ll*a[i].a*t+1)+leq(a[i].a)-1,k-pl))%P;
		}
	}
	sort(a+1,a+n+1,[](student a,student b){
		return a.id<b.id;
	});
	for(int i=1;i<=n;i++){
		cout<<a[i].ans<<'\n';
	}
	
	cout.flush();
	
	/*fclose(stdin);
	fclose(stdout);*/
	return 0;
}