P10704

· · 题解

写了一个很奇怪的做法,跑的倒是很快。

我们令 B 为分治界,然后我们要提前求出 a_i\le B 的 \displaystyle\sum_{j = 1}^{n}\left \lfloor \frac{m}{a_ia_j} \right \rfloor,这里只需整除分块加差分即可。

时间复杂度 $O(n\sqrt B+\frac{m}{B})$,会发现 $B$ 取 $10^5$ 时最优(这个做法不需要 $\displaystyle\sum_{i= 1}^{n} a_i\le10^9$ 的条件,而且跑的非常快)。 # Code ``` #include<bits/stdc++.h> #ifdef ONLINE_JUDGE static char buf[4500000],*p1=buf,*p2=buf; #define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,4500000,stdin),p1==p2)?EOF:*p1++ #endif #define S std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define rep(i,l,r) for(register int i=l;i<=r;i++) #define per(i,l,r) for(register int i=l;i>=r;i--) #define ll long long #define lt __int128 using namespace std; template<typename P>inline void read(P&x){bool f=0;x=0;char c=getchar();while(!isdigit(c)) f|=c=='-',c=getchar();while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();x=f?~(x-1):x;} template<typename P>inline void write(P x){if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar((x%10)^48);} //template<typename P>inline void wu(P x){} #define int long long const int N=1e6+5,M=5e3+5,mod=998244353;const long long inf=1e17; int n,m,a[N],last,ans,len,v[N],cnt[N],c[N],b=1e5; signed main(){ read(n),read(m);rep(i,1,n) read(a[i]);sort(a+1,a+1+n); per(i,n,1) if(v[len]==m/a[i]) cnt[len]++; else v[++len]=m/a[i],cnt[len]=cnt[len-1]+1; rep(i,1,len){ for(register int l=1,r=0;l<=min(b,v[i]);l=r+1){//数论分块 register int o=v[i]/l; r=v[i]/o,r=min(r,b);o%=mod; c[l]+=o*(cnt[i]-cnt[i-1]),c[r+1]-=o*(cnt[i]-cnt[i-1]);//差分 c[l]%=mod,c[r+1]%=mod; } }rep(i,1,b) c[i]=((c[i]+c[i-1])%mod+mod)%mod;//忘记+mod调半天 v[++len]=1e16;//边界 rep(i,1,n){ if(a[i]==a[i-1]){ans=(ans+last)%mod;continue;}last=0; if(a[i]<=b){last=c[a[i]];ans=(ans+last)%mod;continue;}//分治 for(register int j=a[i];j<=m;j+=a[i]){ int l=lower_bound(v+1,v+1+len,j)-v; if(l==len) break;//边界 int r=lower_bound(v+1,v+1+len,j+a[i])-v; if(v[r]>=(j+a[i])){ if(l==r){//对于搜不到时的小优化 j=v[r]/a[i]*a[i]-a[i];//for循环时会加上ai,所以提前减去ai continue; } r--; } last=((j/a[i])*1ll*(cnt[r]-cnt[l-1])%mod+last)%mod; if(r+1==len) break; j=v[r+1]/a[i]*a[i]-a[i];//小优化 }ans=(ans+last)%mod; }write(ans); return 0; } ```