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
posted @ 2021-04-15 19:55  feicheng  阅读(51)  评论(0编辑  收藏  举报