Description
求
∑i=1n∑j=1,j≠im(nmodi)∗(mmodj)
n,m<=10^9,答案模19940417
Solution
首先,看到有%,心里很不爽,把它变成
n−⌊ni⌋∗i
,对于
i≠j
的情况,后面减去就可以了。我们设
n<m
于是原式就变成了
∑i=1n∑j=1m(n−⌊ni⌋∗i)∗(m−⌊mj⌋∗j)−∑i=1n(n−⌊ni⌋∗i)∗(m−⌊mi⌋∗i)
再设
f(n)=∑i=1nn−⌊ni⌋∗i
于是原式就变成了
f(n)∗f(m)−∑i=1n(n−⌊ni⌋∗i)∗(m−⌊mi⌋∗i)
考虑分成两部分计算
Part 1
f(n)=∑i=1nn−⌊ni⌋∗i
=n2−∑i=1n⌊ni⌋∗i
发现 ⌊ni⌋ 最多只有 n√ 种取值,于是我们可以使用分块。(分块大法好!)
设 l 为一段连续的
Part 2
∑i=1n(n−⌊ni⌋∗i)∗(m−⌊mi⌋∗i)
=∑i=1nn∗m−n∗i∗⌊mi⌋−m∗i∗⌊ni⌋+⌊ni⌋∗⌊mi⌋∗i2
=n2∗m+∑i=1ni∗(n∗⌊mi⌋+m∗⌊ni⌋)−⌊ni⌋∗⌊mi⌋∗i2
这样也就可以利用分块大法打出来了。(分块大法好!)
顺便说一下,
∑ni=1i2=n∗(n+1)∗(2∗n+1)6
这里用逆元,6对于19940417的逆元是3323403。(请叫我雷锋(>_<))
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define mo 19940417
#define ni 3323403
using namespace std;
ll n,m,ans;
ll sum(ll l,ll r) {return (l+r)*(r-l+1)/2%mo;}
ll mi(ll n) {
return n*(n+1)%mo*(2*n+1)%mo*ni%mo;
}
ll getan(ll n) {
ll l=1,r;ll an=n*n%mo;
while (l<=n) {
r=(n/(n/l));
an=(an-(n/l)*sum(l,r)%mo+mo)%mo;
l=r+1;
}
return an;
}
int main() {
scanf("%lld%lld",&n,&m);
if (n>m) swap(n,m);
ans=(getan(n)*getan(m)%mo-n*n%mo*m%mo+mo)%mo;
ll l=1,r;
while (l<=n) {
r=min(n/(n/l),m / (m / l));ll x=n / l,y=m / l;
ans=(ans+sum(l,r)*(n*y%mo+m*x%mo)%
mo-(mi(r)-mi(l-1)+mo)%mo*x%mo*y%mo+mo)%mo;
l=r+1;
}
printf("%lld",ans);
}