【2022 省选训练赛 Contest 05 B】卷积练习题(暴力)(性质)
卷积练习题
题目链接:2022 省选训练赛 Contest 05 B
题目大意
给你两个数组,要你求它们各选一个数出来相减的绝对值的平方下取整的结果的和。
然后两个数组里面数的和在 1e7 以内。
思路
考虑从数组和的范围入手。
首先根据第二个部分分不难想到一种做法:记录每个数的出现次数,然后暴力匹配。
然后你再看会这个范围,我们考虑它最多会出现多少种数,而结果是只会出现 \(\sqrt{V}\) 次的(\(V\) 就是数组数的和)
(考虑 \(1+2+3+...+x=\dfrac{x(x-1)}{2}\))
所以这题就是大概每边 \(3000\) 个数,直接暴力就可以过。
然后 WYC 大佬还说如果再大一点比如到 \(1e8\) 的话可以分段搞,前面的用卷积(翻转一边的数组得到相差值为一个值的个数),后面就像这样暴力搞。
代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int n, a[1000001], b[1000001];
int aa[1000001], bb[1000001];
int ma, mb, numa[1000001], numb[1000001];
ll ans;
int clac(int x, int y) {
return floor(sqrt(abs(x - y)));
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
memcpy(aa, a, sizeof(aa)); memcpy(bb, b, sizeof(bb));
sort(aa + 1, aa + n + 1); sort(bb + 1, bb + n + 1);
ma = unique(aa + 1, aa + n + 1) - aa - 1; mb = unique(bb + 1, bb + n + 1) - bb - 1;
for (int i = 1; i <= n; i++) numa[lower_bound(aa + 1, aa + ma + 1, a[i]) - aa]++;
for (int i = 1; i <= n; i++) numb[lower_bound(bb + 1, bb + mb + 1, b[i]) - bb]++;
for (int i = 1; i <= ma; i++)
for (int j = 1; j <= mb; j++)
ans += 1ll * numa[i] * numb[j] * clac(aa[i], bb[j]);
printf("%lld", ans);
return 0;
}