安吉Day4-D
- 1安吉D19 T1
- 2安吉D19 T3
- 3安吉D20 模考12总结
- 4安吉D17 T3
- 5安吉D17 T4
- 6安吉D19 模考11总结
- 7安吉D15 A
- 8安吉D16 T4
- 9安吉D17 T1
- 10安吉D17 模考10总结
- 11安吉D16 T3
- 12安吉D16 模考9总结
- 13安吉D13 模考8总结
- 14安吉D13-T2
- 15安吉D13-T3
- 16安吉D12-T3
- 17安吉D11-B
- 18安吉D11-C
- 19安吉D11-D
- 20安吉D12 模考7总结
- 21安吉D12-T2
- 22安吉D11-A
- 23安吉D10 模考6总结
- 24安吉D10-T3
- 25安吉D10-T4
- 26安吉D8-E
- 27安吉D9-T4
- 28安吉D8-A
- 29安吉D8-B
- 30安吉D8-C
- 31安吉D8-D
- 32安吉D9 模考5总结
- 33安吉D9-T2
- 34安吉D9-T3
- 35安吉D6-T4
- 36安吉D4-G
- 37安吉D5-T2
- 38安吉D6 模考4总结
- 39安吉D6-T1
- 40安吉D6-T3
- 41安吉-开营测试 T4
- 42安吉D5 模考3总结
- 43安吉D5-T3
- 44安吉D4-A
- 45安吉D4-B
- 46安吉D4-C
- 47安吉D4:容斥原理
- 48安吉Day4-D本文
- 49安吉D3 模考2总结
- 50安吉D3-T1
- 51安吉D3-T2
- 52安吉D3-T4
- 53安吉D2 模考1总结
- 54安吉D2-T2
- 55安吉D1-G
- 56安吉D1-L
- 57安吉D2-T4
原题呈现
P10390 因数计数
题目描述
小蓝随手写出了含有 个正整数的数组 ,他发现可以轻松地算出有多少个有序二元组 满足 是 的一个因数.因此他定义一个整数对 是一个整数对 的“因数”当且仅当 和 分别是 和 的因数.他想知道有多少个有序四元组 满足 是 的因数,其中 互不相等.
输入格式
输入的第一行包含一个正整数 . 第二行包含 个正整数 ,相邻整数之间使用一个空格分隔.
输出格式
输出一行包含一个整数表示答案.
输入输出样例 #1
输入 #1
53 6 2 2 7输出 #1
4说明/提示
四元组 : 为 的因子; 四元组 : 为 的因子; 四元组 : 为 的因子; 四元组 : 为 的因子.
对于 的评测用例,; 对于 的评测用例,; 对于所有评测用例,.
在题面中,出现了一个子问题:
求出长度为 的序列 中有多少个有序二元组 满足 .
接下来,我们来解决这个子问题.
考虑到值域只到 ,我们考虑将值域放入数组下标,定义 表示序列 中元素 的数量,并预处理下列数据:
- ,记录序列中是 的倍数的数有多少个(包含 )
- ,记录序列中是 的因数的数有多少个(包含 ) 这些数据可以用调和级数 时间复杂度解决.
接下来,我们就可以使用 ,来计算所有满足 的有序二元组 数量(包括 ).去掉 情况的方法也很简单,显然, 的方法有 种,因此使用 就可以解决上面的子问题.
那么,有序四元对的数量就是 吗?显然不是.我们需要先确定一组满足子问题的有序二元对 ,设 ,由于值域小,我们可以使用枚举 和 的方式来确定一对数值对(此处不需要求出 和 具体是多少,因为后续只会用到 和 ,因此所有 和 分别相等,但 不分别相等的有序二元对是等价的),时间复杂度 .显然,这一对数值对对应着 个有序二元对(如果 则对应 个)这些有序二元对是完全相同的,可以一起处理.
接下来,对于每一对合法的有序二元对 ,我们需要枚举另外一对合法的有序二元对 ,当然,需要满足下面这些条件:
- 且
根据容斥原理,总方案数 有如下表达式:
其中:
- 为上述子问题的答案
- 为 和 中存在一个与 相等的情况,即 或 (),计算方法如下:
- 使用 计算 的倍数有多少个,当 取到 时, 的取值就一定是 的倍数,一共会有 个,由于 ,所以要 -1.
- 使用 计算 的因数有多少个,当 取到 时, 的取值就一定是 的因数,一共会有 个,由于 ,所以要 -1.
- 综合一下,.
- 为 和 中存在一个与 相等的情况,即 或 (),计算方法同上.
- 和 中一个与 相等,另一个与 相等的情况,即 且 ;或 且
- 对于 且 的情况,由于 ,故 恒成立,因此,这种情况一定会有一个贡献为 1.
- 对于 且 的情况,由于 ,当且仅当 时, 成立,故当 时贡献为 1,否则贡献为 0.
得出 之后,数值对 对答案的贡献就是这个数值对对应的有序二元组数量和 之积,具体来说,
- 若 ,贡献为 .
- 否则,贡献为 .
注意,这个题需要开 __int128.
标程
#include <bits/stdc++.h>using namespace std;typedef __int128 lll;const int N = 1e5 + 100;int n, a[N];lll cnt[N], mult[N], divs[N];
void print(lll x) { if (x >= 10) print(x / 10); putchar('0' + x % 10);}
signed main() { cin >> n; int maxa = -1; for (int i = 1; i <= n; i++) { cin >> a[i]; cnt[a[i]]++; maxa = max(maxa, a[i]); } // 预处理 for (int i = 1; i <= maxa; i++) { for (int j = i; j <= maxa; j += i) { mult[i] += cnt[j]; } for (int j = 1; j <= sqrt(i); j++) { if (i % j) continue; divs[i] += cnt[j]; if (j * j != i) { divs[i] += cnt[i / j]; } } } lll T = -n; for (int i = 1; i <= maxa; i++) { T += cnt[i] * mult[i]; } // 计算贡献 lll ans = 0; for (int x = 1; x <= maxa; x++) { for (int y = x; y <= maxa; y += x) { lll Ai = mult[x] + divs[x] - 2; lll Ak = mult[y] + divs[y] - 2; lll Bik = 1 + (x == y); lll tot = T - Ai - Ak + Bik; if (x == y) { ans += (lll)cnt[x] * (cnt[y] - 1) * tot; } else { ans += (lll)cnt[x] * cnt[y] * tot; } } } print(ans);}文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!


