清华集训2012 模积和 题解

清华集训2012 模积和 题解

$\text{Description}$

$n,m\le 10^9$

$\text{Solution}$

发现 $i\neq j$ 很让人不爽,考虑容斥掉:

考虑 $a\bmod{b}=a-b\lfloor\dfrac{a}{b}\rfloor$,有:

前两个就是余数求和的套路,对于后面,考虑 $\sum_{i=1}^ni$ 和 $\sum_{i=1}^n i^2$ 都可以 $O(1)$ 求得,故前缀和十分容易得到,从而用数论分块解决。

$\text{Code}$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<bits/stdc++.h>
#define REG register
#define MOD 19940417
#define LL long long
using namespace std;
inline LL read(){
REG LL x(0);
REG char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=(x*10)+(c^48),c=getchar();
return x;
}
inline LL Min(LL a,LL b){return a<b?a:b;}

LL n,m;

LL ans;

inline LL get1(LL l,LL r){return (r-l+1)%MOD;}
inline LL getId(LL l,LL r){return (l+r)*(r-l+1)%MOD*9970209%MOD;}
inline LL getId2(LL l,LL r){return (r*(r+1)%MOD*(2*r+1)%MOD*3323403%MOD-(l-1)*(l)%MOD*(2*l-1)%MOD*3323403%MOD+MOD)%MOD;}

inline LL divId(LL n,LL m){
LL l=1,r=0,ans=0;
for(;l<=m;l=r+1)
r=Min(m,n/(n/l)),ans=(ans+getId(l,r)*(n/l)%MOD)%MOD;
return ans;
}
inline LL divId2(LL n,LL m){
LL l=1,r=0,ans=0;
for(;l<=m;l=r+1)
r=Min(m,n/(n/l)),ans=(ans+getId2(l,r)%MOD*3323403%MOD);
return ans;
}
inline LL divId2(LL n,LL m,LL k){
LL l=1,r=0,ans=0;
for(;l<=k;l=r+1)
r=Min(Min(k,n/(n/l)),m/(m/l)),ans=(ans+getId2(l,r)*(n/l)%MOD*(m/l)%MOD);
return ans;
}

int main(){
n=read(),m=read();
ans=(n*n%MOD-divId(n,n)+MOD)%MOD;
ans=(m*m%MOD-divId(m,m)+MOD)%MOD*ans%MOD;
LL g=Min(n,m);
ans=(ans-g*n%MOD*m%MOD+MOD)%MOD;
ans=(ans-divId2(n,m,g)+MOD)%MOD;
ans=(ans+m*divId(n,g)%MOD)%MOD;
ans=(ans+n*divId(m,g)%MOD)%MOD;
printf("%lld\n",ans);
}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×