合适数对

合适数对

给定一个长度为 n 的正整数数列 a1,a2,,an 和一个正整数 k

请你判断共有多少个数对 (l,r) 同时满足:

  • 1l<rn
  • 存在一个整数 x 使得 al×ar=xk 成立

输入格式

第一行包含两个整数 n,k

第二行包含 n 个正整数 a1,a2,,an

输出格式

一个整数,表示满足条件的数对的数量。

数据范围

前三个测试点满足 2n10
所有测试点满足 2n1052k1001ai105

输入样例:

6 3
1 3 9 8 24 1

输出样例:

5

 

解题思路

  这题需要用到算术基本定理。对于一个数N=P1α1P2α2Pnαn,如果Nk次幂的话,那么就有kαi,(i=1,2,,n),否则就至少存在一个αi,有kαi。因此这道题目就是要任意找两个数aiaj,使他们的乘积ai×aj的所有质因子的次幂都满足kαi,问有多少对这种数。

  我们枚举j,看j前面有多少个ai使得ai×aj满足条件。先把aj进行质因数分解,得到aj=P1α1P2α2Pnαn,由于我们只关心质因数的次数是否为k的倍数,因此我们只需要关心质因数的次数模k后是否等于0。对于要找的ai=P1β1P2β2Pnβn,应该满足k(αi+βi)(这是对应质因子的次数相加,如果具有不同的质因子,那么另一个数对应的次幂应该等于0,同样满足)。

  由于每一个ai105,我们可以估算一下一个数可以最多分解到多少个不同的质因数,有2×3×5×7×11×13×17>105,因此可以发现每个数最多可以分解到6个不同的质因子。因此每个数最多只有6个质因子的次幂需要补充为k的倍数。

  对于aj,我们找到它分解质因数后所有次幂不是k的倍数的质因子,假设为Pi,假设这些质因子的次幂模k后为ri,容易发现1ri<k。对于ai,其质因数分解后与aj相对应的Pi的次幂模k后为ti,如果对于所有的ri+ti=k都满足,那么这个就是我们要找的ai。补充:因为1ri<k,1ti<kri+ti<2k,因此小于2k且能被k整除的数就只有k

  我们可以直接用次幂模k后不为0的质因子的乘积进行哈希,例如上面的P1r1P2r2PnrnP1t1P2t2Pntn

  AC代码如下:

复制代码
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 typedef long long LL;
 6 
 7 const int N = 1e5 + 10;
 8 
 9 int cnt[N];
10 
11 LL power(int a, int b) {
12     LL ret = 1;
13     while (b--) {
14         ret *= a;
15         if (ret >= N) return 0; // 由于ai都满足<=1e5,因此大于1e5就没有意义了
16     }
17     return ret;
18 }
19 
20 int main() {
21     int n, k;
22     scanf("%d %d", &n, &k);
23     
24     LL ret = 0;
25     while (n--) {
26         int val;
27         scanf("%d", &val);
28         
29         LL p = 1, q = 1;    // p表示对aj来说,次幂模k后不为0的质因子的乘积;q表示对于要找的ai,次幂互补的质因子的乘积
30         for (int i = 2; i <= val / i; i++) {    // 对aj分解质因数
31             int t = 0;
32             while (val % i == 0) {
33                 t = (t + 1) % k;
34                 val /= i;
35             }
36             
37             if (t) {    // 次幂不为0才需要相乘
38                 p *= power(i, t);       // i^t,累乘的结果必然不超过1e5
39                 q *= power(i, k - t);   // 相同质因子的次幂要互补,即i^(k-t),累乘的结果可能超过1e5
40                 if (q >= N) q = 0;      // 超过1e5就没有意义了,赋值为0
41             }
42         }
43         if (val > 1) {
44             p *= val;
45             q *= power(val, k - 1);
46             if (q >= N) q = 0;
47         }
48         
49         ret += cnt[q];
50         cnt[p]++;
51     }
52     
53     printf("%lld", ret);
54     
55     return 0;
56 }
复制代码

  上面的质因数分解的时间复杂度为O(nn)。我们还可以用线性筛,因为线性筛可以得到每一个数的最小质因子,因此在分解质质因数时可以用最小质因子来进行分解,每一个数包含的质因子个数大约为log n个,因此这种方法的时间复杂度为O(nlog n)的。

  AC代码如下:

复制代码
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 typedef long long LL;
 6 
 7 const int N = 1e5 + 10;
 8 
 9 int primes[N], cnt, minp[N];
10 bool vis[N];
11 int mp[N];
12 
13 void get_prime(int n) {
14     for (int i = 2; i <= n; i++) {
15         if (!vis[i]) {
16             primes[cnt++] = i;
17             minp[i] = i;
18         }
19         for (int j = 0; primes[j] <= n / i; j++) {
20             vis[primes[j] * i] = true;
21             minp[primes[j] * i] = primes[j];
22             if (i % primes[j] == 0) break;
23         }
24     }
25 }
26 
27 LL power(int a, int b) {
28     LL ret = 1;
29     while (b--) {
30         ret *= a;
31         if (ret >= N) return 0;
32     }
33     return ret;
34 }
35 
36 int main() {
37     int n, k;
38     scanf("%d %d", &n, &k);
39     
40     get_prime(N);
41     
42     LL ret = 0;
43     while (n--) {
44         int val;
45         scanf("%d", &val);
46         
47         LL p = 1, q = 1;
48         while (val > 1) {
49             int t = minp[val], s = 0;
50             while (val % t == 0) {
51                 s = (s + 1) % k;
52                 val /= t;
53             }
54             
55             p *= power(t, s);
56             if (s) q *= power(t, k - s);
57             if (q >= N) q = 0;
58         }
59         
60         ret += mp[q];
61         mp[p]++;
62     }
63     
64     printf("%lld", ret);
65     
66     return 0;
67 }
复制代码

 

参考资料

  AcWing 4319. 合适数对(AcWing杯 - 周赛):https://www.acwing.com/video/3751/

posted @   onlyblues  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示