手动博客搬家: 本文发表于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级别的数不加取模地连乘,否则必爆。

代码实现

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std; const int NM = 31623;
const long long P = 19940417ll;
long long bl[(NM<<2)+4];
long long tmp[(NM<<2)+4];
long long n,m;
int nm,nn,mm; void modinc(long long &a)
{
if(a<0) a+=P;
if(a>=P) a-=P;
} void merge(int lb1,int lb2,int rb2)
{
int i = lb1,j = lb2,k = lb1;
while(i<=lb2-1 && j<=rb2)
{
if(bl[i]<bl[j]) {tmp[k] = bl[i]; i++;}
else {tmp[k] = bl[j]; j++;}
k++;
}
while(i<=lb2-1) {tmp[k] = bl[i]; i++; k++;}
while(j<=rb2) {tmp[k] = bl[j]; j++; k++;}
for(int i=lb1; i<=rb2; i++) bl[i] = tmp[i];
} long long sqrsum(long long rb)
{
if(rb%3==1) return ((((rb+rb+1)/3)%P)*(rb*(rb+1)/2)%P)%P;
return ((rb*(rb+1)/6)%P*(rb+rb+1))%P;
} long long getsum(long long rb)
{
return (rb*(rb+1)/2)%P;
} long long min_ll(long long x,long long y)
{
return x<y ? x : y;
} int main()
{
scanf("%lld%lld",&n,&m); nm = 0;
nn = sqrt(n); mm = sqrt(m);
for(int i=1; i<=nn; i++) bl[++nm] = i;
for(int i=nn; i>=1; i--) bl[++nm] = n/i;
for(int i=1; i<=mm; i++) bl[++nm] = i;
for(int i=mm; i>=1; i--) bl[++nm] = m/i;
merge(1,1+nn+nn,nm);
long long a = 0ll,b = 0ll,c = 0ll,d = 0ll;
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);}
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);}
c = a*b%P; d = (min_ll(n,m)*n%P)*m%P;
for(int i=1; i<=nm && bl[i]<=min_ll(n,m); i++)
{
long long tmp = (((sqrsum(bl[i])-sqrsum(bl[i-1])+P)*(n/bl[i])%P)*(m/bl[i]))%P;
d += tmp; modinc(d);
}
for(int i=1; i<=nm && bl[i]<=min_ll(n,m); i++)
{
long long tmp = ((getsum(bl[i])-getsum(bl[i-1])+P)*((m*(n/bl[i])+n*(m/bl[i]))%P))%P;
d -= tmp; modinc(d);
}
long long ans = ((n*m)%P)*((n*m)%P)%P;
ans -= (((n*n)%P)*b)%P; modinc(ans);
ans -= (((m*m)%P)*a)%P; modinc(ans);
ans += c; modinc(ans);
ans -= d; modinc(ans);
printf("%lld\n",ans);
return 0;
}

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. extjs的formpanel横向滚动条的解决办法

    关于formpanel设置autoscroll:true同时出现横向和纵向滚动条的解决办法: 不要设置autoscroll属性,或者autoscroll:false,然后设置bodyStyle : ' ...

  2. 循环遍历Java字符串字符的规范方法——类似python for ch in string

    比如我将string作为CNN 文本处理输入: float [] input = new float[maxLength]; // 1 sentence by maxLenWords // int[] ...

  3. hdu1704——floyd

    Problem Description there are N ACMers in HDU team.ZJPCPC Sunny Cup 2007 is coming, and lcy want to ...

  4. 树形dp初步

    其实很早之前就学过树形dp,今天总接一下.树形dp就是一个在树上跑的dp(滑稽) 先是一道板子题:树上最大独立集 直接上代码了. #include<iostream> #include&l ...

  5. 动态规划---区间dp

    今天写内网题,连着写了两道区间dp,这里就总结一下. 区间dp思想主要是先枚举f[i][j]中的i,再枚举j,再枚举一个1~j之间的变量k,一般是f[i][j] = max(f[i][j],f[i][ ...

  6. Aspnet_Session

    cmd: aspnet_regsql.exe -ssadd -sstype c -d ZZCasSession -S 192.168.0.3 -U sa -P szhweb2010 <!--会话 ...

  7. IP地址库

    吐槽 前两天一个线上的IP地址库除了点幺蛾子,一查代码,发现用的库早就不更新了,遂决定换库,有几个方案: 纯真数据库 IPIP数据库 GeoIP 纯真数据库是大码农的福音,免费,但是精度一般:IPIP ...

  8. html中canvas渲染图片,并转化成base64格式保存

    最近在做一个上传头像然后保存显示的功能,因为涉及到裁剪大小和尺寸比例,所以直接上传图片再展示的话,就会出现问题,所以就想用canvas来渲染裁剪后的图片,然后转化成base64格式的图片再存储,这样取 ...

  9. matplotlib之pyplot 学习示例

    现在通过numpy和matplotlib.pyplot 在Python上实现科学计算和绘图,而且和matlab极为相像(效率差点,关键是方便简单) 这里有大量plots代码例子.  1. 简单的绘图( ...

  10. Deutsch lernen (10)

    Dieser Weg Dieser Weg wird kein leichter sein. Dieser Weg wird steinig und schwer. Nicht mit vielen ...