验题人对于计算 $B_1,B_2$ 有一个新的想法:不难发现 $B_2$ 中其实只有 $45000$ 左右个不同的数,那么暴力枚举大概在 $4\times 10^8$,一个是数据不是很极端,再一个是有 $4$s,卡卡常差不多能够通过。
## Code 1
出题人的做法。
```cpp
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
#define mk(x,y) make_pair(x,y)
const int M=1e6+10,N=1e4+10,mod=998244353;
int n,m,gm;
int a[M];
int t[M];
int s[M];
vector<int>b;
int ans=0;
pii ct[M];
int read() {
int x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch > '9') {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + (ch - '0');
ch = getchar();
}
return x * w;
}
signed main(){
freopen("temp.in","r",stdin);
freopen("temp.out","w",stdout);
cin>>n>>m;
gm=ceil(sqrt(m));
for(int i=1;i<=n;i++){
a[i]=read();
if(a[i]<=1e6)t[a[i]]++,s[a[i]]++;
if(a[i]>1e4)b.push_back(a[i]);
}
sort(a+1,a+n+1);
for(int i=1;i<M;i++)s[i]+=s[i-1];
for(int i=1;i<=1e4;i++){
for(int j=1;j<=1e4;j++){
ans=(ans+m/(i*j)*t[i]%mod*t[j]%mod)%mod;
}
}
int l=1,r;
while(l<=m){
r=m/(m/l);
if(m/l<=gm)ct[m/l]=mk(l,r);
l=r+1;
}
for(int i=1;i<=m/1e8;i++){
for(int j:b){
int l=ct[i].first,r=ct[i].second;
l=ceil(1.0*l/j),r=r/j;
if(l>r||r<=1e4)continue;
l=max(l,(int)1e4+1);
int nex=s[r]-s[l-1];
ans+=nex*i;
if(ans>mod)ans%=mod;
}
}
for(int i=1;i<=1e3;i++){
for(int j:b){
ans+=m/(i*j)*t[i]*2;
if(ans>mod)ans%=mod;
}
}
for(int i=1;i<=m/1e7;i++){
for(int j:b){
int l=ct[i].first,r=ct[i].second;
l=ceil(1.0*l/j),r=r/j;
if(l>r||r<=1e3||l>1e4)continue;
if(r>1e4)r=1e4;
if(l<=1e3)l=1e3+1;
int nex=s[r]-s[l-1];
ans+=nex*i*2;
if(ans>mod)ans%=mod;
}
}
cout<<ans<<endl;
return 0;
}
```
## Code 2
验题人的做法。
```cpp
#include <bits/stdc++.h>
typedef long long LL;
const int M = 1e6 + 10, B = 1500;
const int mod = 998244353;
const LL Max_m = 1e10;
LL m, ans;
int n, a[M], pre[Max_m / B + 10];
std::vector<std::pair<int, int> > S, S0, S1;
inline void Init() {
std::map<int, int> mp;
for (int i = 1; i <= n; i++)
if (a[i] <= B) ++mp[a[i]];
for (auto x : mp) S0.emplace_back(x);
std::sort(S0.begin(), S0.end());
for (int i = 1; i <= n; i++)
if (a[i] > B) ++mp[a[i]];
for (auto x : mp) S.emplace_back(x);
std::sort(S.begin(), S.end());
mp.clear();
for (int i = 1; i <= n; i++)
if (a[i] > B) ++mp[a[i]];
for (auto x : mp) S1.emplace_back(x);
std::sort(S1.begin(), S1.end());
}
int main() {
scanf("%d%lld", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
Init();
for (auto [x, a] : S) {
LL v = m / x;
for (auto [y, b] : S0) {
if (x < y) break;
if (1ll * x * y > m) break;
if (x == y)
ans += 1ll * a * b % mod * (v / y % mod);
else
ans += 2ll * a * b % mod * (v / y % mod);
ans %= mod;
}
}
for (auto [x, a] : S1)
if (x <= m / B) pre[x] += a;
for (int i = B; i <= m / B; i++) pre[i] += pre[i - 1];
for (LL l = 1, r; l <= m; l = r + 1) {
r = m / (m / l);
if (m / l <= m / B / B)
for (auto [x, a] : S1) {
LL p = m / l;
LL _l = l / x + (bool)(l % x), _r = r / x;
// m / (x * y) = p
// _l <= y <= _r
if (_r >= _l) {
ans += 1ll * pre[_r] * p % mod * a % mod;
if (_l > 0) ans += mod - 1ll * pre[_l - 1] * p % mod * a % mod;
ans %= mod;
}
}
}
printf("%lld\n", ans);
return 0;
}
```