[sum_{i=1}^{n}sum_{j=1}^{m}(n mod i) imes(m mod j)\
=sum_{i=1}^{n}sum_{j=1}^{m}(n-ilfloordfrac{n}{i}
floor)(m-jlfloordfrac{m}{j}
floor)\
=sum_{i=1}^{n}(n-ilfloordfrac{n}{i}
floor)sum_{j=1}^{m}(m-jlfloordfrac{m}{j}
floor)\
=(n^2-sum_{i=1}^{n}idfrac{n}{i})(m^2-sum_{i=1}^{m}idfrac{m}{i})
]
整除分块没了
写完后发现自己惊奇地过不了样例
发现原式后面还有个 (i ot=j) ,那就。。。
直接减去即可((n<m))
[sum_{i=1}^{n}(n mod i)(m mod i)\
=sum_{i=1}^{n} (n-idfrac{n}{i})(m-idfrac{m}{i})\
=sum_{i=1}^{n}(nm-m*idfrac{n}{i}-n*idfrac{m}{i}+i^2dfrac{n}{i}dfrac{m}{i})\
=n^2m-msum_{i=1}^{n}idfrac{n}{i}-nsum_{i=1}^{n}idfrac{m}{i}+sum_{i=1}^{n}i^2dfrac{n}{i}dfrac{m}{i}
]
还是整除分块
那个二次方和需要处理 (6) 的逆元
写了个快速幂,照理 (h(5)=55) ,但是怎么都过不去。
第一时间查快速幂,还真挂了。。但是还是挂
忽然想起那个模数有没有可能不是质数
打开终端,factor 19940417
,发现是 (7) 的倍数 真毒瘤
线性递推逆元即可
#include<bits/stdc++.h>
typedef long long LL;
typedef double db;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f?x:-x;
}
const int mod=19940417;
int qpow(int n,int k){int res=1;for(;k;k>>=1,n=1ll*n*n%mod)if(k&1)res=1ll*n*res%mod;return res;}
int n,m,ans,inv[7];
int f(int n){
int res=0;
for(int l=1,r,t;l<=n;l=r+1)
r=n/(n/l),t=1ll*(r-l+1)*(l+r)/2%mod,res=(res+1ll*t*(n/l)%mod)%mod;
return (res+mod)%mod;
}
int h(int n){
return 1ll*n*(n+1)%mod*(n+n+1)%mod*inv[6]%mod;
}
int g(int n,int m){
int res=1ll*n*m%mod*n%mod;
res=(res-1ll*m*f(n)%mod)%mod;
int tmp=0;
for(int l=1,r,t;l<=n;l=r+1)
r=std::min(n,m/(m/l)),t=1ll*(l+r)*(r-l+1)/2%mod,tmp=(tmp+1ll*t*(m/l)%mod)%mod;
res=(res-1ll*tmp*n%mod)%mod;
for(int l=1,r;l<=n;l=r+1)
r=std::min(n/(n/l),m/(m/l)),res=(res+1ll*(h(r)-h(l-1))*(n/l)%mod*(m/l)%mod)%mod;
return (res+mod)%mod;
}
signed main(){
inv[1]=1;
for(int i=2;i<=6;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
n=read(),m=read();
if(n>m)std::swap(n,m);
printf("%lld
",(1ll*(1ll*n*n%mod-f(n)+mod)*(1ll*m*m%mod-f(m)+mod)%mod-g(n,m)+mod)%mod);
}