手动博客搬家: 本文发表于20170223 16:47:26, 原地址https://blog.csdn.net/suncongbo/article/details/79354835

题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=2956

题目大意: 求$$\sum^{n}{i=1} \sum^{m}{j=1, j\ne i} (n \mod i)(m \mod j)$$对19940417取模的值。

思路分析:

从heheda神犇的博客“heheda的数论专题练习”上翻到这样一道比较有趣的题。

一开始想歪了,一直在考虑n mod i与n mod (i+1)之间的递推关系,后来发现行不通。

既然是取模,那就可以采用“化模为除”的方法,即利用公式$$n \mod i = n-[n/i]*i $$化简原式,暂且不考虑\(i\ne j\)的条件可得$$ans=\sum^{n}{i=1} \sum^{m}{j=1} (n-i[n/i])(m-j[m/j])

= \sum^{n}{i=1} \sum^{m}{j=1} (nm-nj[m/j]-mi[n/i]+ij[n/i][m/j])

= n2m2-n2\sum{m}{j=1}j[m/j]-m2\sum{n}{i=1}i[m/i]+\sum{n}_{i=1}i[n/i]*\sum{m}_{j=1}j[m/j]$$

做到这一步,既然只有i和[n/i]出现在式子里(j同理),显然可以用数论分块加速这个过程了。(至于数论分块的实现可以参见我的另一篇博客http://blog.csdn.net/suncongbo/article/details/78819470) 分成\((2\sqrt n+2\sqrt m)\)个块,每个块内的\([n/i]\)与\([m/i]\)值均不变,块内求和直接用求和公式$$getsum(n)=\frac{n(n+1)}{2}$$, 块内求和等于块右端点的getsum返回值减去块左端点的getsum返回值。

然后去掉\(i=j\)的情况:$$\sum^{\min(n,m)}{i=1} (n-i[n/i])(m-i[m/i])

=\sum{\min(n,m)}_{i=1}(nm-ni[m/i]-mi[n/i]+i2[n/i][m/i])

=nm\min(n,m)-\sum{min(n,m)}_{i=1}i(n[m/i]+m[n/i])+\sum{min(n,m)}
{i=1}i^2[n/i][m/i]$$, 前两项仍然可以用前面的方法进行计算。棘手的问题来了:

对于最后一项,牵扯到求连续自然数的平方和。我们知道$$sqrsum(i)=\sum{n}_{i=1}i2=\frac{n(n+1)(2n+1)}{6}$$, 但是如果把\(n(n+1)(2n+1)\)算出来将会很大,long long无法支持。因此只能中途对\(19940417\)取模。但是又要除以6,牵扯到求逆元,而19940417又不是质数,无法用费马小定理求逆元。此时做法一是通过其他方法(如exgcd)求出6对于\(19940417\)的逆元,二是直接算出6的逆元并作为常量使用。其实,这个数的值是\(3323403\).

而我使用的是第三种做法——分类讨论。(其实是因为懒得写逆元)

观察到当\(n\equiv 0\)或\(n\equiv 2 (\mod 3)\)时,\(n(n+1)\)的值可以被6整除,因此先算出\(\frac{n(n+1)}{6}\)即可。当\(n\equiv 1 (\mod 3)\)时,\(2n+1\)被3整除,\(n(n+1)\)被2整除,故计算\(\frac{2n+1}{3}\)与\(\frac{n(n+1)}{2}\)相乘即可。(当然如果模数是24而不是6我甘愿老老实实地求逆元)

注意运算符优先级问题,不可以有任何连着三个19940417或1e9级别的数不加取模地连乘,否则必爆。

代码实现

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cmath>
  4. using namespace std;
  5. const int NM = 31623;
  6. const long long P = 19940417ll;
  7. long long bl[(NM<<2)+4];
  8. long long tmp[(NM<<2)+4];
  9. long long n,m;
  10. int nm,nn,mm;
  11. void modinc(long long &a)
  12. {
  13. if(a<0) a+=P;
  14. if(a>=P) a-=P;
  15. }
  16. void merge(int lb1,int lb2,int rb2)
  17. {
  18. int i = lb1,j = lb2,k = lb1;
  19. while(i<=lb2-1 && j<=rb2)
  20. {
  21. if(bl[i]<bl[j]) {tmp[k] = bl[i]; i++;}
  22. else {tmp[k] = bl[j]; j++;}
  23. k++;
  24. }
  25. while(i<=lb2-1) {tmp[k] = bl[i]; i++; k++;}
  26. while(j<=rb2) {tmp[k] = bl[j]; j++; k++;}
  27. for(int i=lb1; i<=rb2; i++) bl[i] = tmp[i];
  28. }
  29. long long sqrsum(long long rb)
  30. {
  31. if(rb%3==1) return ((((rb+rb+1)/3)%P)*(rb*(rb+1)/2)%P)%P;
  32. return ((rb*(rb+1)/6)%P*(rb+rb+1))%P;
  33. }
  34. long long getsum(long long rb)
  35. {
  36. return (rb*(rb+1)/2)%P;
  37. }
  38. long long min_ll(long long x,long long y)
  39. {
  40. return x<y ? x : y;
  41. }
  42. int main()
  43. {
  44. scanf("%lld%lld",&n,&m); nm = 0;
  45. nn = sqrt(n); mm = sqrt(m);
  46. for(int i=1; i<=nn; i++) bl[++nm] = i;
  47. for(int i=nn; i>=1; i--) bl[++nm] = n/i;
  48. for(int i=1; i<=mm; i++) bl[++nm] = i;
  49. for(int i=mm; i>=1; i--) bl[++nm] = m/i;
  50. merge(1,1+nn+nn,nm);
  51. long long a = 0ll,b = 0ll,c = 0ll,d = 0ll;
  52. for(int i=1; i<=nm && bl[i]<=n; i++) {a += (getsum(bl[i])-getsum(bl[i-1])+P)*(n/bl[i])%P; modinc(a);}
  53. for(int i=1; i<=nm && bl[i]<=m; i++) {b += (getsum(bl[i])-getsum(bl[i-1])+P)*(m/bl[i])%P; modinc(b);}
  54. c = a*b%P; d = (min_ll(n,m)*n%P)*m%P;
  55. for(int i=1; i<=nm && bl[i]<=min_ll(n,m); i++)
  56. {
  57. long long tmp = (((sqrsum(bl[i])-sqrsum(bl[i-1])+P)*(n/bl[i])%P)*(m/bl[i]))%P;
  58. d += tmp; modinc(d);
  59. }
  60. for(int i=1; i<=nm && bl[i]<=min_ll(n,m); i++)
  61. {
  62. long long tmp = ((getsum(bl[i])-getsum(bl[i-1])+P)*((m*(n/bl[i])+n*(m/bl[i]))%P))%P;
  63. d -= tmp; modinc(d);
  64. }
  65. long long ans = ((n*m)%P)*((n*m)%P)%P;
  66. ans -= (((n*n)%P)*b)%P; modinc(ans);
  67. ans -= (((m*m)%P)*a)%P; modinc(ans);
  68. ans += c; modinc(ans);
  69. ans -= d; modinc(ans);
  70. printf("%lld\n",ans);
  71. return 0;
  72. }

BZOJ 2956 模积和 (数学推导+数论分块)的更多相关文章

  1. [Bzoj 2956] 模积和 (整除分块)

    整除分块 一般形式:\(\sum_{i = 1}^n \lfloor \frac{n}{i} \rfloor * f(i)\). 需要一种高效求得函数 \(f(i)\) 的前缀和的方法,比如等差等比数 ...

  2. BZOJ 2956 模积和(分块)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2956 [题目大意] 求∑∑((n%i)*(m%j))其中1<=i<=n,1 ...

  3. bzoj 2956: 模积和 ——数论

    Description 求∑∑((n mod i)*(m mod j))其中1<=i<=n,1<=j<=m,i≠j. Input 第一行两个数n,m. Output 一个整数表 ...

  4. BZOJ 2956 模积和

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2956 题意:给出n和m.计算: 思路: i64 n,m; i64 cal(i64 m,i ...

  5. 【BZOJ】2956: 模积和

    题意 求\(\sum_{i=1}^{n} \sum_{j=1}^{m} (n \ mod \ i)(m \ mod \ j)[i \neq j] \ mod \ 19940417\), \((n, m ...

  6. bzoj 3994 约数个数和 —— 反演+数论分块

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3994 推导过程和这里一样:https://www.cnblogs.com/MashiroSk ...

  7. BZOJ 3119 Book (贪心+数学推导)

    手动博客搬家: 本文发表于20191029 22:49:41, 原地址https://blog.csdn.net/suncongbo/article/details/78388925 URL: htt ...

  8. 【BZOJ】2956:模积和

    Time Limit: 10 Sec  Memory Limit: 128 MB Description 求∑∑((n mod i)*(m mod j))其中1<=i<=n,1<=j ...

  9. BZOJ 1968_P1403 [AHOI2005]约数研究--p2260bzoj2956-模积和∑----信息学中的数论分块

    第一部分 P1403 [AHOI2005]约数研究 题目描述 科学家们在Samuel星球上的探险得到了丰富的能源储备,这使得空间站中大型计算机“Samuel II”的长时间运算成为了可能.由于在去年一 ...

随机推荐

  1. mongoDB学习笔记——在C#中查询

    1.下载安装 想要在C#中使用MongoDB,首先得要有个MongoDB支持的C#版的驱动.C#版的驱动貌似有很多种,如官方提供的samus. 实现思路大都类似.这里我们用官方提供的mongo-csh ...

  2. luogu1631 序列合并

    题目大意 有两个序列A,B,在A和B中各取一个数相加能得到$n^2$个和.求出这些和前n小的数字. 题解 首先这道题不可以用自己想的什么A序列B序列各两个指针的自己发明的模拟算法,用这样的算法只能是绝 ...

  3. 【Git学习笔记】用git pull取回远程仓库某个分支的更新,再与本地的指定分支自动merge【转】

    本文转载自:http://blog.csdn.net/liuchunming033/article/details/45367629 git pull的作用是,从远程库中获取某个分支的更新,再与本地指 ...

  4. 为什么倒排索引不采用zlib这样的字典压缩算法——因为没法直接使用啊

    看了下压缩算法的发展历史,根据倒排索引的数据结构特点,个人认为zstd不适合做倒排索引压缩,举例说明下: 假设有一份文档倒排列表为:[300, 302, 303, 332],对于这组倒排数据,是没法* ...

  5. nyoj--1100--WAJUEJI which home strong!(bfs)

    WAJUEJI which home strong! 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 在一个山沟里,姐弟俩同时考上了大学.但由于家里拮据,所以这并不是什么 ...

  6. codeforces round #424 div2

    A 暴力查询,分三段查就可以了 #include<bits/stdc++.h> using namespace std; ; int n, pos; int a[N]; int main( ...

  7. Redis(四)-配置

    Redis 配置 Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf. 你可以通过 CONFIG 命令查看或设置配置项. 语法 Redis CONFIG 命令格式如下: ...

  8. css 继承性和层叠性

    css有两大特性:继承性和层叠性 继承性 面向对象语言都会存在继承的概念,在面向对象语言中,继承的特点:继承了父类的属性和方法.那么我们现在主要研究css,css就是在设置属性的.不会牵扯到方法的层面 ...

  9. Bootstrap中container与container-fluid的区别

    /*0-768px以上宽度container为100%*/ .container { padding-right: 15px; padding-left: 15px; margin-right: au ...

  10. ES6 学习小结1

    ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015. 也就是说,ES6就是ES2015. ...