题目相关
题目链接
AtCoder Regular Contest 107 B 题,https://atcoder.jp/contests/arc107/tasks/arc107_b。
Problem Statement
Given are integers N and K. How many quadruples of integers (a,b,c,d) satisfy both of the following conditions?
- 1 ≤ a,b,c,d ≤ N
- a+b−c−d=K
Input
Input is given from Standard Input in the following format:
N K
Output
Print the answer.
Samples1
Sample Input 1
2 1
Sample Output 1
4
Explaination
Four quadruples below satisfy the conditions:
- (a,b,c,d)=(2,1,1,1)
- (a,b,c,d)=(1,2,1,1)
- (a,b,c,d)=(2,2,2,1)
- (a,b,c,d)=(2,2,1,2)
Samples2
Sample Input 2
2525 -425
Sample Output 2
10314607400
Constraints
- 1≤N≤10^5
- −2(N−1)≤K≤2(N−1)
- All numbers in input are integers.
题解报告
题目翻译
给定两个整数 N 和 K,在 1 ~ N 中,有几个四元组 (a, b, c, d) 满足 a+b-c-d=K。
题目分析
首先不要被四元组给迷惑,题目只是要求求出数量,而不是找出所有的四元组。因此本题核心还是一个纯数学问题。
任何一个题目,我们都可以先考虑暴力枚举。由于数据的最大值为 10^5,使用暴力枚举四元组 (a, b, c, d) ,对应的时间复杂度就是 。即使简单优化,变成暴力枚举三元组,时间复杂度也是 。意味着最大可能需要计算 ,这肯定是一个 TLE 算法。
简化成为二元组
题目给出一个四元组计算,我们考虑一个简化版本,也就是两元组计算。即满足 a+b=K。或者量化看,a=9、b=7 和 k=13。我们可以枚举 a,通过 b=k-a 来计算 b。也就是说,我们只需要枚举以下可能两元组:
(1, k-1)
(2, k-2)
.
.
.
(k-2, 2)
(k-1, 1)
统计这些两元组中有几个可能存在就可以得到答案。这样就是一个 O(N) 的算法。
为什么是从 1 开始枚举呢?题目告诉我们 。
四元组问题
通过上面的描述,我们可以将四元组转换为二元组,也就是将 a+b 看成一个数,c+d 看成另外一个数,这样 a+b-c-d=k 的问题,就可以转化成为一个二元组问题。
根据题目给出的数据,我们知道 1 ≤ a,b,c,d ≤ N,也就意味着 2 ≤ a+b, c+d ≤ 2*N。这样问题就化简为一个 O(N) 级别。
数据分析
由于在计算中,需要使用到乘法原理,最大数据可能是 ,必须使用 long long 这个数据类型表示。
AC 参考代码
//https://atcoder.jp/contests/arc107/tasks/arc107_b
//B - Quadruple
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n,k;
LL solve(LL sum) {
LL tot = sum-1;
LL sub = max(0LL, sum-n-1);
return max(0LL, tot-2*sub);
}
int main() {
cin>>n>>k;
LL ans=0;
for (LL i=k; i<=2*n; i++) {
ans += (solve(i)*solve(i-k));
}
cout<<ans<<"\n";
return 0;
}
代码细节
可能有人要问 max() 这个函数。
首先、max() 出自 STL 的 algorithm 库。
其次、max() 只能比较相同数据类型,所以使用 0LL 这个小技巧。表示这是一个 long long 的 0。