4315. 两个数列
题目描述
有两个正整数数列 a 1 , a 2 , … , a n a1,a2,…,an a1,a2,…,an 和 b 1 , b 2 , … , b n b1,b2,…,bn b1,b2,…,bn。
现在,已知的信息有:
- 数列 a a a 的各个元素的值。
- 数列 b b b 的各个元素之和 s s s。
- 对于任意的 1 ≤ i ≤ n 1≤i≤n 1≤i≤n,满足 1 ≤ b i ≤ a i 1≤b_i≤a_i 1≤bi≤ai 成立。
由上述信息,我们可知对于元素 b i b_i bi,其可能的取值范围为 [ 1 , a i ] [1,a_i] [1,ai],但是受到已知条件的约束,它可能无法取到其中一些数值。
我们的任务就是计算每个 b i b_i bi 在其可能的取值范围内,无法取到的数值的数量。
例如,如果 n = 2 , a = { 4 , 4 } , s = 8 n=2,a=\{4,4\},s=8 n=2,a={4,4},s=8,则数列 b b b 中的每一个元素都不能小于 4 4 4(否则,另一个元素就要大于 4 4 4,这是不可能的),也就是说 b 1 b_1 b1 和 b 2 b_2 b2 在其可能的取值范围 [ 1 , 4 ] [1,4] [1,4] 内,均无法取到 1 , 2 , 3 1,2,3 1,2,3,无法取到的数值的数量均为 3 3 3。
输入格式
第一行包含两个整数 n n n 和 s s s。
第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,…,an。
输出格式
共一行, n n n 个整数,其中第 i i i 个整数表示 b i b_i bi 在其可能的取值范围内,无法取到的数值的数量。
数据范围
前三个测试点满足
1
≤
n
≤
2
1≤n≤2
1≤n≤2。
所有测试点满足
1
≤
n
≤
2
×
1
0
5
,
n
≤
s
≤
∑
i
=
1
n
a
i
,
1
≤
a
i
≤
1
0
6
1≤n≤2×10^5,n \leq s \leq \sum_{i=1}^{n} a_{i},1≤a_i≤10^6
1≤n≤2×105,n≤s≤∑i=1nai,1≤ai≤106。
输入样例1:
2 8
4 4
输出样例1:
3 3
输入样例2:
1 3
5
输出样例2:
4
输入样例3:
2 3
2 3
输出样例3:
0 1
解题思路
其实就是解一个不等式,用数学推导公式~
下面我们来推导一下公式!
已知有两个正整数数列:
a
1
,
a
2
,
…
,
a
n
a1,a2,…,an
a1,a2,…,an
b
1
,
b
2
,
…
,
b
n
b1,b2,…,bn
b1,b2,…,bn
b
b
b的各个元素之和为
S
S
S,即
S
=
b
1
+
b
2
+
.
.
.
+
b
n
S=b_1+b_2+...+b_n
S=b1+b2+...+bn;
令
S
i
=
b
1
+
b
2
+
.
.
.
b
i
−
1
+
b
i
+
1
.
.
.
+
b
n
S_i=b_1+b_2+...b_{i-1}+b_{i+1}...+b_n
Si=b1+b2+...bi−1+bi+1...+bn,
S
u
m
=
a
1
+
a
2
+
.
.
.
+
a
n
Sum=a_1+a_2+...+a_n
Sum=a1+a2+...+an;
又因为,对于任意的
1
≤
i
≤
n
1≤i≤n
1≤i≤n,满足
1
≤
b
i
≤
a
i
1≤b_i≤a_i
1≤bi≤ai 成立;
则:
n
−
1
≤
S
i
≤
S
u
m
−
a
i
n-1≤S_i≤Sum-a_i
n−1≤Si≤Sum−ai;
−
n
+
1
≥
−
S
i
≥
−
S
u
m
+
a
i
-n+1\geq -S_i\geq -Sum+a_i
−n+1≥−Si≥−Sum+ai
S
−
n
+
1
≥
S
−
S
i
≥
S
−
S
u
m
+
a
i
S-n+1\geq S-S_i\geq S-Sum+a_i
S−n+1≥S−Si≥S−Sum+ai
又因为
S
−
S
i
=
b
i
S-S_i=b_i
S−Si=bi,则有
S
−
n
+
1
≥
b
i
≥
S
−
S
u
m
+
a
i
S-n+1\geq b_i\geq S-Sum+a_i
S−n+1≥bi≥S−Sum+ai
最终我们只需要取
1
≤
b
i
≤
a
i
1≤b_i≤a_i
1≤bi≤ai集合和
S
−
n
+
1
≥
b
i
≥
S
−
S
u
m
+
a
i
S-n+1\geq b_i\geq S-Sum+a_i
S−n+1≥bi≥S−Sum+ai集合的交集即可!~
又因为
n
≤
S
≤
S
u
m
n \leq S \leq Sum
n≤S≤Sum
即
b
i
b_i
bi的取值范围大概在
[
n
−
S
u
m
+
a
i
,
S
u
m
−
n
+
1
]
[n-Sum+a_i,Sum-n+1]
[n−Sum+ai,Sum−n+1],
由于测试点满足
1
≤
n
≤
2
×
1
0
5
,
n
≤
s
≤
∑
i
=
1
n
a
i
,
1
≤
a
i
≤
1
0
6
1≤n≤2×10^5,n \leq s \leq \sum_{i=1}^{n} a_{i},1≤a_i≤10^6
1≤n≤2×105,n≤s≤∑i=1nai,1≤ai≤106。
所以集合
S
−
n
+
1
≥
b
i
≥
S
−
S
u
m
+
a
i
S-n+1\geq b_i\geq S-Sum+a_i
S−n+1≥bi≥S−Sum+ai的取值范围在
[
1
,
2
×
1
0
11
]
[1,2×10^{11}]
[1,2×1011]与集合
1
≤
b
i
≤
a
i
1≤b_i≤a_i
1≤bi≤ai(取值范围大约在
[
1
,
1
0
6
]
[1,10^6]
[1,106]),所以数据保证是一定有交集的,所以情况三不存在,即集合长度
d
=
m
i
n
(
b
,
d
)
−
m
a
x
(
a
,
c
)
+
1
d=min(b,d)-max(a,c)+1
d=min(b,d)−max(a,c)+1;
c++代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int n;
LL s;
int a[N];
LL get(LL a, LL b, LL c, LL d)
{
return min(b, d) - max(a, c) + 1;
}
int main()
{
scanf("%d%lld", &n, &s);
LL sum = 0;
/*读入a数组,并计算a1+a2+...+an*/
for (int i = 1; i <= n; i ++ )
{
scanf("%d", &a[i]);
sum += a[i];
}
for (int i = 1; i <= n; i ++ )//输出答案~
printf("%d ", a[i] - get(s - sum + a[i], s - n + 1, 1, a[i]));
return 0;
}