文章目录

  • 前提知识复习
  • T1:余数求和
    • title
    • solution
    • code
  • T2:Ice Rain
    • title
    • solution
    • code
  • T3:The Fool
    • title
    • solution
    • code
  • T4:模积和
    • title
    • solution
    • code

前提知识复习

整除分块是用于快速处理形似下列式子的方法,是解决莫比乌斯反演类题目需要掌握的前提知识
∑i=1n⌊ni⌋\sum_{i=1}^n\lfloor\frac{n}{i}\rfloori=1∑n​⌊in​⌋
但是本篇博客的例题是特别特别板的,不会涉及莫比乌斯反演,请dalao们出门左转别浪费时间,蟹蟹
回归正题,很显然上面的式子可以O(n)O(n)O(n)得到答案
但是,在某些题目中,毒瘤出题人将数据加强到了 101010^{10}1010以上
这个时候我们就无法通过O(n)O(n)O(n) 的解法来得到答案
我们需要一个O(n)O(\sqrt{n})O(n​)的更为优秀的解法

对于单一的⌊ni⌋\lfloor\frac{n}{i}\rfloor⌊in​⌋,某些地方的值是相同的,并且呈块状分布
通过深入的探求规律与严密推理以及暴力打表与幸运瞎猜 ,最后惊奇的发现这些块状分布的值是有规律的
对于一个块,假设它的起始位置的下标为lll,那么可以得到的是,它的结束位置的下标为
代码表示即为

r = n / ( n / l );

分块如果非要安排一个模板的话,那就是一个forforfor循环了

int calc( int n ) {int ans = 0;for( int l = 1, r;l <= n;l = r + 1 ) {r = n / ( n / l );//根据题目要求进行计算 }return ans;
}

有的时候不同的题目可能出现n/l==0n/l==0n/l==0的情况,为了防止程序挂掉,我们也可以这么写

int calc( int n ) {int ans = 0;for( int l = 1, r;l <= n;l = r + 1 ) {if( k / l ) r = min( k / ( k / l ), n );else r = n;//根据题目要求进行计算}return ans;
}

具体的就用例题来体会吧

T1:余数求和

title

添加链接描述

solution

G(n,k)=∑i=1nkmodi=∑i=1n(k−⌊ki⌋∗i)=∑i=1nk−∑i=1n⌊ki⌋∗iG(n,k)= ∑_{i=1}^n k\ mod\ i=\sum_{i=1}^n(k-\lfloor\frac{k}{i}\rfloor*i)=\sum_{i=1}^nk-\sum_{i=1}^n\lfloor\frac{k}{i}\rfloor*iG(n,k)=i=1∑n​k mod i=i=1∑n​(k−⌊ik​⌋∗i)=i=1∑n​k−i=1∑n​⌊ik​⌋∗i
前面的求和式子可以很直观地得到∑i=1nk=n∗k\sum_{i=1}^nk=n*k∑i=1n​k=n∗k
后面的求和式子我们令lll表示这个块的开始下标,rrr为这个块的结束下标,T=⌊ni⌋T=\lfloor\frac{n}{i}\rfloorT=⌊in​⌋,则该块里面的值为:
∑i=lrT∗i=∑i=lrT−∑i=lri\sum_{i=l}^rT*i=\sum_{i=l}^rT-\sum_{i=l}^rii=l∑r​T∗i=i=l∑r​T−i=l∑r​i
答案显而易见了吧,第一个求和就是个定值(r−l+1)∗T(r-l+1)*T(r−l+1)∗T,后面的求和就是等差数列

计算方法:首项加末项乘以项数除以二=>(l+r)∗(r−l+1)/2(l+r)*(r-l+1)/2(l+r)∗(r−l+1)/2

code

#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
signed main() {int n, k;scanf( "%lld %lld", &n, &k );int ans = n * k;for( int l = 1, r;l <= n;l = r + 1 ) {if( k / l ) r = min ( k / ( k / l ), n );else r = n;ans -= ( r - l + 1 ) * ( k / l ) * ( l + r ) / 2;}printf( "%lld", ans );return 0;
}

T2:Ice Rain

title

添加链接描述

solution

读完题后是不是

一模一样的吧,这种sb题 你加一个无线输入操作就ACACAC,passpasspass,下一个!!

code

#include <cstdio>
#include <iostream>
using namespace std;int main() {long long n, k;while( ~ scanf( "%lld %lld", &n, &k ) ) {long long ans = n * k;for( long long l = 1, r;l <= n;l = r + 1 ) {if( k / l ) r = min( k / ( k / l ), n );else r = n;ans -= ( k / l ) * ( l + r ) * ( r - l + 1 ) / 2;}printf( "%lld\n", ans );}return 0;
}

T3:The Fool

title

添加链接描述

solution

一样的吧?差不多的吧?如果你没有一点思路的话,证明我写的太差 没有学懂哦~
∑i=1n⌊ni⌋∑_{i=1}^n \lfloor\frac{n}{i}\rfloor∑i=1n​⌊in​⌋,先分出每个块,然后再等差数列求和,加在一起最后判断,vanvanvan事

code

#include <cstdio>
int main() {int T;scanf( "%d", &T );for( int Case = 1;Case <= T;Case ++ ) {long long n;scanf( "%lld", &n );long long ans = 0;for( int l = 1, r;l <= n;l = r + 1 ) {r = n / ( n / l );ans += ( r - l + 1 ) * ( n / l );} if( ans & 1 ) printf( "Case %d: odd\n", Case );else printf( "Case %d: even\n", Case );}return 0;
}

T4:模积和

title

添加链接描述

solution

这道题就是个重头戏了,其实也很简单的
仔细看推导过程!!
ans=∑i=1n∑j=1m(nmodi)×(mmodj),i≠jans=∑_{i=1}^n∑_{j=1}^m(n\ mod\ i)×(m\ mod\ j),i≠jans=i=1∑n​j=1∑m​(n mod i)×(m mod j),i​=j
用容斥拆开把i=ji=ji=j的情况减掉即可
ans=∑i=1n∑j=1m(nmodi)×(mmodj)−∑i=1min(n,m)(nmodi)×(mmodi)ans=∑_{i=1}^n∑_{j=1}^m(n\ mod\ i)×(m\ mod\ j)-∑_{i=1}^{min(n,m)}(n\ mod\ i)×(m\ mod\ i)ans=i=1∑n​j=1∑m​(n mod i)×(m mod j)−i=1∑min(n,m)​(n mod i)×(m mod i)
直接把显而易见能分块的先分了来,再暴力展开
∑i=1n(nmodi)=∑i=1nn−∑i=1n⌊ni⌋∗i∑_{i=1}^n(n\ mod\ i)=\sum_{i=1}^nn-\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor*ii=1∑n​(n mod i)=i=1∑n​n−i=1∑n​⌊in​⌋∗i
∑j=1m(mmodj)=∑j=1mm−∑j=1m⌊mj⌋∗j∑_{j=1}^m(m\ mod\ j)=\sum_{j=1}^mm-\sum_{j=1}^m\lfloor\frac{m}{j}\rfloor*jj=1∑m​(m mod j)=j=1∑m​m−j=1∑m​⌊jm​⌋∗j
∑i=1min(n,m)(nmodi)×(mmodi)=∑i=1min(n,m)(n−⌊ni⌋∗i)∗(m−⌊mi⌋∗i)∑_{i=1}^{min(n,m)}(n\ mod\ i)×(m\ mod\ i)=\sum_{i=1}^{min(n,m)}(n-\lfloor\frac{n}{i}\rfloor*i)*(m-\lfloor\frac{m}{i}\rfloor*i)i=1∑min(n,m)​(n mod i)×(m mod i)=i=1∑min(n,m)​(n−⌊in​⌋∗i)∗(m−⌊im​⌋∗i)
=∑i=1min(n,m)(nm+⌊mi⌋⌊ni⌋i2−⌊mi⌋i−⌊ni⌋i)=\sum_{i=1}^{min(n,m)}(nm+\lfloor\frac{m}{i}\rfloor\lfloor\frac{n}{i}\rfloor i^2-\lfloor\frac{m}{i}\rfloor i-\lfloor\frac{n}{i}\rfloor i)=i=1∑min(n,m)​(nm+⌊im​⌋⌊in​⌋i2−⌊im​⌋i−⌊in​⌋i)
整理综上

ans=(∑i=1nn−∑i=1n⌊ni⌋∗i)(∑i=1mm−∑i=1m⌊mi⌋∗i)−∑i=1min(n,m)(nm+⌊mi⌋⌊ni⌋i2−⌊mi⌋i−⌊ni⌋i)ans=(\sum_{i=1}^nn-\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor*i)(\sum_{i=1}^mm-\sum_{i=1}^m\lfloor\frac{m}{i}\rfloor*i)-\sum_{i=1}^{min(n,m)}(nm+\lfloor\frac{m}{i}\rfloor\lfloor\frac{n}{i}\rfloor i^2-\lfloor\frac{m}{i}\rfloor i-\lfloor\frac{n}{i}\rfloor i)ans=(i=1∑n​n−i=1∑n​⌊in​⌋∗i)(i=1∑m​m−i=1∑m​⌊im​⌋∗i)−i=1∑min(n,m)​(nm+⌊im​⌋⌊in​⌋i2−⌊im​⌋i−⌊in​⌋i)
最后我们发现i2i^2i2在分块的时候挂掉了,OMG,怎么办!!,告诉你一个结论

∑ini2=n∗(n+1)∗(2n+1)/2∑_i^ni^2=n∗(n+1)∗(2n+1)/2i∑n​i2=n∗(n+1)∗(2n+1)/2


最后注意避雷!!!ppp不是个质数,稍微用随便找个互质的数搞个逆元就好了

code

#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
#define mod 19940417
int n, m, inv;int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}int sqr( int x ) {return x * ( x + 1 ) % mod * ( x << 1 | 1 ) % mod * inv % mod;
}int sum( int l, int r ) {return ( l + r ) * ( r - l + 1 ) / 2 % mod;
}int calc( int n ) {int ans = 0;for( int l = 1, r;l <= n;l = r + 1 ) {r = n / ( n / l );ans = ( ans + n * ( r - l + 1 ) % mod - ( n / l ) * sum( l, r ) % mod + mod ) % mod;}return ans;
}signed main() {inv = qkpow( 6, 17091779 );scanf( "%lld %lld", &n, &m );int ans = calc( n ) * calc( m ) % mod;if( n > m ) swap( n, m );for( int l = 1, r;l <= n;l = r + 1 ) {r = min( n / ( n / l ), m / ( m / l ) );int sum1 = n * m % mod * ( r - l + 1 ) % mod;int sum2 = ( n / l ) * ( m / l ) % mod * ( sqr( r ) - sqr( l - 1 ) + mod ) % mod;int sum3 = ( n / l * m % mod + m / l * n % mod ) * sum( l, r ) % mod;ans = ( ans - ( sum1 + sum2 - sum3 + mod ) % mod + mod ) % mod;}printf( "%lld", ans );return 0;
}

走了,题还没做完…

数论分块专题复习(余数求和+模积和+Ice Rain+The Fool)相关推荐

  1. 【数论】数论分块(详细,小白):余数求和约数研究

    数论分块 标题数论分块是一种非常重要的思想.就是对于一些表达式,它的值只有sqrt(n)种,那么我们就对于这sqrt(n)种数值进行分块,然后暴力算即可. 简单来说就是: 把一个数列分成一块一块的区域 ...

  2. P2260 [清华集训2012]模积和,P2834 能力测验(二维除法分块)

    P2260 [清华集训2012]模积和 推导过程 我们假定n<=mn <= mn<=m ∑i=1n∑j=1m(nmodi)(mmodj),i≠j\sum_{i = 1} ^{n} ...

  3. P2261 [CQOI2007]余数求和 整除分块

    传送门 文章目录 题意: 思路: 题意: n,k≤1e9n,k\le1e9n,k≤1e9 思路: 考虑转换式子,∑i=1nkmodi=∑i=1n(k−⌊ki⌋∗i)=n∗k−∑i=1n⌊ki⌋∗i\s ...

  4. 【数论】整除分块(数论分块)

    目录 引入 找规律 分块数量(时间复杂度分析) 分块边界 模板 例题 1.约束研究 2.约数和 3.余数求和 4.Fear Factoring 5.Floor and Mod 引入 整除分块是数论问题 ...

  5. 乘法逆元 +数论分块 +平方和公式

    年后准备学习啦,开学还得准备考试. 乘法逆元: 因为涉及到除法,所以取余这个操作就错误. 所以如果我们要求(a/b)%mod,我们可以假设 (a/b)%mod = a*c%mod 那么c就是b的逆元. ...

  6. HDU6395 Sequence(矩阵快速幂+数论分块)

    题意: F(1)=A,F(2)=B,F(n)=C*F(n-2)+D*F(n-1)+P/n 给定ABCDPn,求F(n) mod 1e9+7 思路: P/n在一段n里是不变的,可以数论分块,再在每一段里 ...

  7. BZOJ 2956 模积和

    题目链接:模积和 这种有模运算的题一般都要把取模运算给去掉,改成除法取下整的模式.即\(a\bmod b=a-\lfloor \frac{a}{b} \rfloor b\) 然后我们先把\(i=j\) ...

  8. 洛谷 P2261 [CQOI2007]余数求和 解题报告

    P2261 [CQOI2007]余数求和 题意: 求\(G(n,k)=\sum_{i=1}^n k \ mod \ i\) 数据范围: \(1 \le n,k \le 10^9\) \(G(n,k)\ ...

  9. 宏观经济学思维导图_巧用思维导图,提升初三化学专题复习课实效

    旭东化学,你的教学助手  你关注的  正是我们专注的      关注教育 |  关注教学 | 关注化学 立即关注      初中化学知识分布比较零散,内容较为抽象,学生复习记忆比较困难.而思维导图作为 ...

最新文章

  1. Mac上搭建Nginx + rtmp
  2. php创建view,GitHub - houdunwang/laravel-view: Laravel 视图组件生成器
  3. tcp假连接_总结的23 个 TCP高频面试问题
  4. Java类集-set
  5. 华为、中兴圈地IPTV金矿 中小企业南柯一梦
  6. Redhat Enterprise Linux 5系统引导故障解决方法
  7. 【Flutter】Dart的类方法和对象操作符
  8. 数字签名工具signtool
  9. 如何用ps修改图片文字颜色
  10. 吴恩达深度学习02-3.567 Batch Normalization(BN)
  11. Summary——CrowdPose: Efficient Crowded Scenes Pose Estimation and A New Benchmark
  12. Android内存泄漏总结,一线互联网公司面经总结
  13. 编程生成一个瓶子(1)
  14. LASSO和LARS
  15. JavaWeb——404错误
  16. swiper.js显示指定图片
  17. 上周热点回顾(8.20-8.26)
  18. 点,破折号和花花公子表现得很差
  19. php工程师是干什么的
  20. eeglab学习记录(1)-eeglab安装+导入EDF数据

热门文章

  1. 了解IT行业前沿应用,关注数据与算法之美
  2. 有趣!机器学习预测《守望先锋》里的赢家
  3. 怎样安装python在桌面_在Windows上安装和配置 Jupyter Lab 作为桌面级应用程序教程...
  4. python引用numpy出错_使用numpy时出错
  5. java一般方法有哪些方法有哪些方法_Java代码优化有哪些方法?
  6. php输出PDF的文件流_怎么用PHP在HTML中生成PDF文件
  7. mysql 大小写 if_【已解决】Windows下 MySQL大小写敏感 解决方案及分析
  8. php 如何生成exe文件怎么打开,如何把PHP转成EXE文件
  9. python大型项目中的日志模块_Python中日志模块的使用
  10. matlab eval函数_matlab自动给变量命名