LG7517 [省选联考 2021 B 卷] 数对

LG7517 [省选联考 2021 B 卷] 数对

前言

省选撞题不是第一次了

居然还撞这么水的

场外选手来胡一波题解。

解法

我一开始搞了个暴力,是这样做的。

我们发现 \(a_i\) 的范围很小,可以搞一个桶 \(tot\)

离散化之后枚举每个数的所有倍数,累加计数。对于相同的数字,可以用 \(tot_i\cdot(tot_i-1)\) 计算,累加到 \(ans\) 上输出即可。

没想到过了qwq。

仔细一想确实是对的。

我们令 \(ma=\max\limits_{i=1}^n a_i\)\(m\) 为离散化后的数的个数。

那么时间复杂度为 \(O(\sum\limits_{i=1}^m \frac{ma}{a_i})\)。按照数据范围,你构造极限数据,满打满算就是 \(O(6288448)\)。随便加常数也都过了。

极限数据附下

200000
1 2 3...199997 199998 199999 500000

代码

//Don't act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you'll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
#define int long long//想不到吧,我开了long long。/cy
using namespace std;

int read() {
	char ch=getchar();
	int f=1,x=0;
	while(ch<'0'||ch>'9') {
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		x=x*10+ch-'0';
		ch=getchar();
	}
	return f*x;
}

const int MAXN=5e5+10;

int n,m,ma,ans;
int a[MAXN],tot[MAXN];
//聪明的同学可能会问了。
//你没开 long long 怎么过的?
//是洛谷数据太水了吗?
//达咩达咩~
//我开了!
//只有聪明的人看得到我开了 long long。

signed main() {
	cin>>n;
	for(int i=1;i<=n;i++) {
		a[i]=read();
		ma=max(ma,a[i]);
		tot[a[i]]++;
	}
	
	sort(a+1,a+n+1);
	m=unique(a+1,a+n+1)-a-1;
    //离散化

	for(int i=1;i<=m;i++) {
		for(int j=a[i]*2;j<=ma;j+=a[i]) {
            //一倍的a[i]直接算,从2*a[i]开始循环
			ans+=tot[j]*tot[a[i]];
		}
		ans+=tot[a[i]]*(tot[a[i]]-1);
	}
	
	cout<<ans<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/huayucaiji/p/LG7517.html