- 给定(n)个整数(a_i)。保证(1leq a_ileq m) 。
对于每个(1leq xleq m),求出$$sum_{i=1}^{n}([frac {a_i}{x}]+[frac {x}{a_i}])$$
- 不会打向下取整……那两个中括号是向下取整。
- 还比较好的题,这两个东西可以分开求。
- 先考虑前面那个,就是考虑对于一个(x),考虑(k*x)到(k*x+k-1)中间的(a_i)有多少。
- 然后这一些(a_i)都可以产生(k)的贡献,前缀和统计就好了。
- 后面考虑的是对于每一个(a_i),他能产生增量贡献的(x)有哪一些。
- 也就是说,对于一个(a_i),在(k*a_i)处,都会相比之前增加(1)的贡献。
- 所以也是差分后前缀和统计就好了。
- 注意第一个式子,如果对于任意(w_i=1)的情况都直接做的话,复杂度就不是调和级数了。
- 所以要把相等的数都缩起来,枚举值域。
- 复杂度(O(mlogm))
#include<bits/stdc++.h>
#define R register int
#define ll long long
#define db double
using namespace std;
const int N=3000001;
int n,m,w[N];
ll G[N],P[N],T[N],ans;
int gi(){
R x=0,k=1;char c=getchar();
while((c<'0'||c>'9')&&c!='-')c=getchar();
if(c=='-')k=-1,c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*k;
}
int main(){
n=gi(),m=gi();
for(R i=1;i<=n;++i)w[i]=gi(),G[w[i]]++;
sort(w+1,w+n+1);
for(R i=1;i<=m;++i)
if(G[i])
for(R j=i;j<=m;j+=i)
T[j]+=G[i];
for(R i=1;i<=m;++i)T[i]+=T[i-1],G[i]+=G[i-1];
for(R i=1;i<=m;++i){
for(R k=i;k<=m;k+=i)
P[i]+=(G[min(m,k+i-1)]-G[k-1])*(k/i);
}
for(R i=1;i<=m;++i)ans^=(P[i]+T[i]);
printf("%lld
",ans);
return 0;
}