原题解链接:https://ac.nowcoder.com/discuss/149990

cnt[y]cnt[y] aia_iyy的出现次数。

首先对于每个1xm1 \leq x \leq m 考虑 i=1naix\sum_{i=1}^{n}\left\lfloor\frac{a_{i}}{x}\right\rfloor, 我们发现如果 aix=k\left\lfloor\frac{a_{i}}{x}\right\rfloor=k,那么k×xai<(k+1)×xk \times x \leq a_{i}<(k+1) \times x,是一个区间。 所以我们可以首先枚举xx,再枚举xx的倍数k×xk\times x,然后把cnt[k×x]cnt[(k+1)×x1]\operatorname{cnt}[k \times x] \sim \operatorname{cnt}[(k+1) \times x-1]统计进答案即可。

然后考虑xAi\left\lfloor\frac{x}{A_{i}}\right\rfloor。我们发现当xxk×ai1k\times a_i-1变为k×aik \times a_i时,这个值多了11。所以我们可以对于每个aia_i,枚举它的倍数,然后往这个倍数的位置打上+1+1的标记,最后前缀和即可求出每个位置的答案。

但是这样做的复杂度为i=1nmai=O(n×m)\sum_{i=1}^{n}\left\lfloor\frac{m}{a_{i}}\right\rfloor=O(n \times m)(当aia_i都很小时)。

改进一下,如果有多个aia_i的值相同,那么这些aia_i打的标记都相同。所以我们可以改为枚举每个值1ym1≤y≤m,枚举yy的倍数,然后一次就打+cnt[y]+cnt[y]的标记。

复杂度为i=1mmi=O(mlogm)\sum_{i=1}^{m}\left\lfloor\frac{m}{i}\right\rfloor=O(m \log m)

	#include<bits/stdc++.h>
	#define maxn 2000010
	#define ll long long
	using namespace std;
	
	int a[maxn],b[maxn],n,m;
	ll tag[maxn],ans=0;
	inline void read(int &x){
		char ch=x=0;
		while(!isdigit(ch))
			ch=getchar();
		while(isdigit(ch))
			x=x*10+ch-'0',ch=getchar();
	}
	int main(){
		read(n),read(m);
			for(int i=1;i<=n;i++)
				read(a[i]),b[a[i]]++;
		for(int i=1;i<=m;i++){
			for(int j=i;j<=m;j+=i)
				tag[j]+=b[i];
		}
		for(int i=1;i<=m;i++)
			b[i]+=b[i-1],tag[i]+=tag[i-1];
		
		for(int i=1;i<=m;i++){
			for(int j=1;j*i<=m;j++){
				int st=i*j,ed=min(m,i*(j+1)-1);
				tag[i]+=1LL*(b[ed]-b[st-1])*j;
			}
		}
		for(int i=1;i<=m;i++)
			ans^=tag[i];
		printf("%lld\n",ans);
		return 0;
	}