jzoj 5588 %%%
Sol:
取反以后数论分块。
code:
#include<bits/stdc++.h> #define LL long long using namespace std; LL ans,n,m,pos,be,ed,epos,eval; int T; LL get1(LL l,LL r) { if (l<m&&r<m) return (l+r)*(r-l+1)/2; if (l<m&&r>=m) return (l+m)*(m-l+1)/2+(r-m)*m; return (r-l+1)*m; } LL get2(LL l,LL r) { m--; pos=n/l; be=n-pos*r; ed=n-pos*l; if (ed<=m) return m++,(r-l+1)*(be+ed)/2; epos=(n-m)/pos+((n-m)%pos>0?1:0); eval=n-pos*epos; return m++,(r-epos+1)*(be+eval)/2+(epos-l)*(m-1); } signed main () { freopen("mod.in","r",stdin); freopen("mod.out","w",stdout); scanf("%d",&T); while (T--) { scanf("%lld%lld",&n,&m); ans=0; if (m==0) {printf("%lld\n",n*n); continue;} for (LL i=1,last;i<=n;i=last+1) { last=n/(n/i); ans+=n/i*get1(i,last); ans+=get2(i,last); } printf("%lld\n",n*n-ans); } return 0; }