题意
求 $sum_{i=1}^n sum_{j=1}^m (n mod i)*(m mod j)$($i eq j$),$n,m leq 10^9$答案对 $19940417$ 取模。
分析:
由于取模可化成取整的形式,$k mod i = k - left lfloor frac{k}{i} ight floor * i$,详见 BZOJ1257 余数之和。
易知,$sum_{i=1}^n sum_{j=1}^m (n mod i)*(m mod j) = sum_{i=1}^n(n mod i)sum_{j=1}^m(m mod j)$
所以答案为两部分余数和的乘积减去 $i$ 等于 $j$ 的情况,
当 $i=j$ 时,
$$
egin{aligned}
sum_{i=1}^{min(n,m)}(n mod i)(m mod i) & = sum_{i=1}^{min(n,m)}(n - left lfloor frac{n}{i}
ight
floor i)(m - left lfloor frac{m}{i}
ight
floor i) \
&= sum_{i=1}^{min(n,m)}(nm - mleft lfloor frac{n}{i}
ight
floor i - nleft lfloor frac{m}{i}
ight
floor i + left lfloor frac{n}{i}
ight
floor left lfloor frac{m}{i}
ight
floor i^2) \
end{aligned}$$
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 19940417; const ll inv6 = 3323403; ll n, m; //sum_1^n [k/i]*i ll S1(ll n, ll k) { ll ret = 0; if(k <= n) //需要分类讨论 { for(ll i = 1,j;i <= k;i = j+1) { j = k / (k / i); ret = (ret + (i+j) * (j-i+1) / 2 % mod * (k / i) % mod) % mod; } } else { for(ll i = 1,j;i <= n;i = j+1) { j = min(k / (k / i), n); ret = (ret + (i+j) * (j-i+1) / 2 % mod * (k / i) % mod) % mod; } } return ret; } ll S2(ll n) { n %= mod; return n * (n+1) % mod * (2*n+1) % mod * inv6 % mod; } //[n/i][m/i]i^2 ll S3(ll n, ll m) { ll ret = 0; for(ll i = 1,j;i <= min(n, m);i = j+1) { j = min(n/(n/i), m/(m/i)); ret = (ret + (n/i) * (m/i) % mod * (S2(j) - S2(i-1)) % mod) % mod; } return ret; } int main() { scanf("%d%d", &n, &m); if(m > n) swap(n, m); ll ans = 1; ans = ans * (n*n%mod - S1(n, n) + mod) % mod; ans = ans * (m*m%mod - S1(m, m) + mod) % mod; ll ans2 = n *m % mod * m % mod; ans2 = (ans2 - m * S1(m, n) % mod) % mod; ans2 = (ans2 - n * S1(m, m) % mod) % mod; ans2 = (ans2 + S3(n, m)) % mod; //printf("%lld %lld ", ans, ans2); printf("%lld ", (ans - ans2 + 2*mod) % mod); return 0; }