本文搬运自本人初中博客园博客,若图片加载不出来,可到原文查看:https://www.cnblogs.com/zhangtingxi/p/16531877.html

题目地址

题目

i=1nj=1m(nmodi)×(mmodj),ij\sum_{i=1}^{n} \sum_{j=1}^{m} (n \bmod i) \times (m \bmod j), i \neq j

mod 19940417 的值

image

思路

nmn\leq m

i=1n(nmodi)×j=1m(mmodj)i=1n(nmodi)(mmodi)\Large\sum_{i=1}^{n} (n \bmod i) \times \sum_{j=1}^{m}(m \bmod j)-\sum_{i=1}^ n (n\bmod i)(m\bmod i)

前面那两坨就是个数论分块板子,后面那块拆一下:

i=1n(nmmi×inni×im+mi×ni×i2)\Large \sum_{i=1}^n(nm-\frac m i\times in-\frac n i \times im+\frac m i\times\frac n i\times i^2)

这里还是可以数论分块,每次块的 rr 可以取 min(ml,nl)\min(\dfrac m l, \dfrac n l)

然后还有几个难点

  1. 后面那坨鬼东西乘 i2i^2,众所周知二次方和公式 i=1ni2=n(n+1)(2n+1)6\sum_{i=1}^n i^2=\dfrac {n(n+1)(2n+1)}6

  2. 然后上面那个鬼公式因为上面三个乘起来会爆所以要用逆元

  3. 然后因为↑↓出题人模数不是质数不能用费马只能老老实实打拓欧

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Problem: P2260 [清华集训2012]模积和
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2260
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M
#define mo 19940417
//#define N
int n, m, i, j, k, T;
int ans, l, r, P;

int kuai(int a, int b)
{
int ans=1;
while(b)
{
if(b&1) ans*=a;
a*=a; b>>=1;
ans%=mo; a%=mo;
}
return ans;
}

void exgcd(int a, int b, int &x, int &y)
{
if(b==0) x=1, y=0;
else
{
exgcd(b, a%b, x, y);
int z=y;
y=x-a/b*y;
x=z;
}
}

int calc(int n)
{
int ans=n*n%mo, l, r;
for(l=1; l<=n; l=r+1)
{
r=min(n, n/(n/l));
ans-=(l+r)*(r-l+1)/2%mo*(n/l)%mo;
ans%=mo;
}
return ans;
}

int sim(int n)
{
return n*(n+1)%mo*(2*n+1)%mo*P%mo;
}

int suan(int l, int r)
{
return (sim(r)-sim(l-1))%mo;
}

signed main()
{
// freopen("tiaoshi.in", "r", stdin);
// freopen("tiaoshi.out", "w", stdout);
exgcd(6, mo, P, T);
n=read(); m=read();
if(n>m) swap(n, m);
ans=calc(n)*calc(m)%mo;
for(l=1; l<=n; l=r+1)
{
r=min({n, n/(n/l), m/(m/l)});
ans-=(r-l+1)*n%mo*m%mo;
ans+=(l+r)*(r-l+1)/2%mo*n%mo*(m/l)%mo;
ans+=(l+r)*(r-l+1)/2%mo*m%mo*(n/l)%mo;
ans-=(m/l)*(n/l)%mo*suan(l, r)%mo;
ans=(ans%mo+mo)%mo;
}
printf("%lld\n", ans);
return 0;
}

总结

本题考察一下知识点;

  1. 式子化简(是个人都会)
  2. 数论分块(在学,这几天做个笔记)和其拓展应用(如本题)
  3. 二次和公式(以前用过,但忘了)
  4. 拓欧求逆元(学了又忘,再学又忘,还是要靠推)