4319. 合适数对

题目链接

4319. 合适数对

给定一个长度为 n 的正整数数列 a1,a2,,an 和一个正整数 k。  请你判断共有多少个数对 (l,r) 同时满足:

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

输入格式

第一行包含两个整数 n,k。 
第二行包含 n 个正整数 a1,a2,,an

输出格式

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

数据范围

前三个测试点满足 2n10
所有测试点满足 2n1052k1001ai105
输入样例:

63 1398241

输出样例:

5

解题思路

算术基本定理

一个数可以表示为若干个素数幂次方乘积的形式,固定 ar,假设其表示为 p1c1p2c2pncn,如果存在 ci%k=0,则不用管这个素数,因为如果前面存在该素数的幂次 cj%k0,则这个数肯定不用统计到答案里面去,而如果前面存在该素数的幂次 cj%k=0,则由于没管这个素数,所以对答案的统计没有影响,而对于当前数 ar 的一个素数的幂次 ci,要求找到这样的一种数:它的所有素数的幂次 cj=kci%k,而这样的数根据算术基本定理又是唯一的,可以直接根据值进行哈希

  • 时间复杂度:O(nlogn)

代码

  • 哈希
// Problem: 合适数对 // Contest: AcWing // URL: https://www.acwing.com/problem/content/4322/ // Memory Limit: 256 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1e5+5; int n,k,a[N]; map<vector<PII>,int> mp; LL res; vector<PII> v,t; void divide(int x) { for(int i=2;i<=x/i;i++) if(x%i==0) { int c=0; while(x%i==0)x/=i,c++; if(c%k)v.pb({i,c%k}),t.pb({i,k-c%k}); } if(x>1)v.pb({x,1}),t.pb({x,k-1}); } int main() { cin>>n>>k; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++) { v.clear(); t.clear(); divide(a[i]); res+=mp[t]; mp[v]++; } cout<<res; return 0; }
  • 朴素分解质因数
// Problem: 合适数对 // Contest: AcWing // URL: https://www.acwing.com/problem/content/4322/ // Memory Limit: 256 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1e5+5; int n,k,a[N]; int cnt[N],t,tt; LL res; void divide(int x) { t=1,tt=1; for(int i=2;i<=x/i;i++) if(x%i==0) { int c=0; while(x%i==0)x/=i,c++; c%=k; if(c) { for(int j=0;j<c;j++)t*=i; for(int j=0;j<k-c;j++) { if(1ll*tt*i>=N) { tt=0; break; } tt*=i; } } } if(x>1) { t*=x; for(int j=0;j<k-1;j++) { if(1ll*tt*x>=N) { tt=0; break; } tt*=x; } } } int main() { cin>>n>>k; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++) { divide(a[i]); res+=cnt[tt]; cnt[t]++; } cout<<res; return 0; }
  • 欧拉分解质因数
// Problem: 合适数对 // Contest: AcWing // URL: https://www.acwing.com/problem/content/4322/ // Memory Limit: 256 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1e5+5; int n,k,a[N]; int cnt[N],t,tt; LL res; int prime[N],m,v[N]; void primes(int n) { for(int i=2;i<=n;i++) { if(!v[i])v[i]=i,prime[++m]=i; for(int j=1;j<=m;j++) { if(prime[j]>n/i||v[i]<prime[j])break; v[i*prime[j]]=prime[j]; } } } void divide(int x) { int lst=0,cnt=0; t=1,tt=1; while(x!=1) { if(lst==0)cnt=1; else if(v[x]==lst)cnt++; else { if(cnt%k) { for(int i=0;i<cnt%k;i++)t*=lst; for(int i=0;i<k-cnt%k;i++) { if(1ll*tt*lst>=N) { tt=0; break; } tt*=lst; } } cnt=1; } lst=v[x],x/=v[x]; } if(cnt%k) { for(int i=0;i<cnt%k;i++)t*=lst; for(int i=0;i<k-cnt%k;i++) { if(1ll*tt*lst>=N) { tt=0; break; } tt*=lst; } } } int main() { cin>>n>>k; primes(N-1); for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++) { divide(a[i]); res+=cnt[tt]; cnt[t]++; } cout<<res; return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16064153.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示