P7517 数对 题解
Preface
考场心路历程:第一眼看到题以为是 GOSICK。
结果发现是个全局询问,顿时就没难度了。
Descrpition
给定长度为 \(n\) 的序列 \(a\),求满足 \(a_i = k\times a_j(k\in N_+,i\not = j)\) 的二元组 \((i,j)\) 有多少个。
restrictions:\(1 \le n \le 2\times 10^5,1\le a_i\le5\times 10^5\)
Solution
我的做法是根号的(那会想到了根号想来应该能过就没写 polylog 的)。
具体来说,就是对于每一个 \(a_i\) ,开一个桶统计其贡献。
它的贡献就是:对于所有 \(a_i\),枚举其因数,给因数的 sum
\(+1\),
最后将贡献累计起来即可。
最后特判一下 \(1\) 即可。
时间复杂度 \(\Theta(n\sqrt{\max a_i})\)。
Code
考场代码:
#include <bits/stdc++.h>
typedef long long ll ;
typedef unsigned long long u64 ;
namespace hpy {
const int HL = 1 << 20 ;
char buf[HL],buff[HL],*t1 = buf,*t2 = buf,*T = buff ;
inline char getc() {
return t1 == t2 && (t2 =(t1 = buf)+fread(buf,1,HL,stdin),t1 == t2) ? EOF : *t1 ++ ;
}
inline void flush() {
fwrite(buff,1,T-buff,stdout),T = buff;
}
inline void putc(const char ch) {
if(T == buff + HL) flush() ;
*T ++ = ch ;
}
struct Read {
template <typename Tp>
inline Read& operator >> (Tp &x) {
char ch = getc();
int f = 0;
for(;!isdigit(ch);ch = getc()) f = (ch == '-') ? 1 : 0 ;
x = 0;
for(;isdigit(ch);ch = getc()) x = (x<<3) + (x<<1) + (ch^48) ;
return x = f ? -x : x,*this ;
}
inline Read& operator >> (char &ch) {
ch = getc() ;
while(ch == ' ' || ch == '\n') ch = getc() ;
return *this ;
}
inline Read& operator >> (char *str) {
int len = 0 ;
char ch = getc() ;
while(ch == ' ' || ch == '\n') ch = getc() ;
while(ch != ' ' && ch != '\n' && ch != '\r' && ch != EOF) str[len++] = ch,ch = getc() ;
return *this ;
}
Read() {}
} hin;
struct Write {
template <typename Tp>
inline Write& operator << (Tp x) {
if (!x) return putc('0'),*this ;
if(x < 0) x = -x,putc('-') ;
int stk[20],top = 0;
while(x) stk[++top] = x%10,x/=10;
while(top) putc(stk[top--] + '0') ;
return *this;
}
inline Write& operator << (char ch) {
return putc(ch),*this ;
}
inline Write& operator << (char *str) {
int len = 0 ;
while(str[len]) putc(str[len++]) ;
return *this ;
}
inline Write& operator << (const char *str) {
int len = 0 ;
while(str[len]) putc(str[len++]) ;
return *this ;
}
} hout;
inline int ksm(int x,int y,int p) {
int res = 1;
for(;y;y >>= 1,x = 1ll*x*x % p) if(y&1) res = 1ll*res*x%p;
return res ;
}
}
using hpy::hin ;
using hpy::hout ;
using hpy::ksm ;
using std::max ;
const int N = 2e5 + 10;
const int M = 5e5 + 10;
int a[N];
ll sum[M],tim[M];
int n,mx ;
inline void file() {
freopen("pair.in","r",stdin) ;
freopen("pair.out","w",stdout) ;
}
int main() {
file();
hin >> n ;
ll ans = 0 ;
for(int i = 1;i <= n;++i) hin >> a[i],mx = max(mx,a[i]),++tim[a[i]];
for(int i = 1;i <= n;++i) {
if(a[i] == 1) {
ans += n - 1; // 1 能对所有数产生贡献
continue ;
}
for(int j = 2;j <= sqrt(a[i]);++j) {
if(a[i]%j == 0) {
++sum[j] ;
if(a[i] != j*j) ++sum[a[i]/j] ;
}
}
}
for(int i = 1;i <= n;++i) ans += sum[a[i]];
for(int i = 1;i <= n;++i) ans += a[i] == 1? 0 : tim[a[i]] - 1 ;//特判,这里统计的是一倍之间的贡献,由于 1 已经被统计了所以去除掉
hout << ans ;
return hpy::flush(),0;
}
//lyy,cz,smh,yhy ak SNOI
//lyy tql
//cz tql
//yhy tql
//smh tql