模积和(bzoj 2956)
求∑∑((n mod i)*(m mod j))其中1<=i<=n,1<=j<=m,i≠j。
对于100%的数据n,m<=10^9。
对于而言,他的个数很小,最大是63244,因此可以枚举分块确定区域 [ l , n/(n/l) ]
c++ code:
#include <bits/stdc++.h> using namespace std; const int mod=19940417; const int ni=3323403; typedef long long ll; ll sum(ll l,ll r) { return (r-l+1)*(l+r)/2%mod; } ll cal(ll n) { ll l,r,ans=n*n%mod; l=1; while(l<=n) { r=n/(n/l); ans=(ans-(n/l)*sum(l,r)%mod+mod)%mod; l=r+1; } return ans; } ll pre(ll l,ll r) { return (r*(r+1)%mod*(2*r+1)%mod*ni%mod-l*(l+1)%mod*(2*l+1)%mod*ni%mod+mod)%mod; } int main() { ll m,n; scanf("%lld%lld",&m,&n); if(m<n) swap(m,n); ll ans=(cal(n)*cal(m)%mod-n*n%mod*m%mod+mod)%mod; ll l=1,r; while(l<=n) { ll x,y; r=min(n/(n/l),m/(m/l)); x=n/l;y=m/l; ans=(ans+sum(l,r)*(n*y%mod+m*x%mod)%mod-x*y%mod*pre(l-1,r)%mod+mod)%mod; l=r+1; } printf("%lld\n",ans); return 0; }