为什么我连分块都想不到啊...


题意

定义一个矩阵$f$满足

$ f(a,b)=f(b,a)$

$ b·f(a,a+b)=(a+b)·f(a,b)$

初始$ f(a,b)=ab$

有$ m$次修改,每次会将$ f(x,y)$改成$ c$,并修改这个矩阵使得仍然满足以上两条

保证修改后矩阵中每个数均为正整数

你需要在每次修改后求出$ \sum\limits_{i=1}^k\sum\limits_{j=1}^kf(i,j)$

数据范围满足$ m \leq 10000$,涉及到的矩形范围不超过$4·10^6$


$Solution $

给定的信息类似一个辗转相减的过程

和求$ gcd(x,y)$的过程非常像

我们不断辗转相减可以得到$ f(x,y)=f(d,d)*\frac{xy}{d^2}$

其中$ d=gcd(x,y)$

考虑求答案的式子的意义

$ ans=\sum\limits_{i=1}^k\sum\limits_{j=1}^kf(i,j)$

$ans=\sum\limits_{k=1}^nf(k,k)\sum\limits_{i=1}^{\frac{n}{k}}\sum\limits_{j=1}^{\frac{n}{k}}ij[gcd(i,j)=1]$

$ A(n)=\sum\limits_{i=1}^n\sum\limits_{j=1}^nij[gcd(i,j)=1]$

$A(n)=\sum\limits_{i=1}^n i^2\varphi(i)$

原理是若$ x<y,x和y互质则y-x和y互质$

这样可以化简为

$ans=\sum\limits_{k=1}^nf(k,k)A(\frac{n}{k})$

显然$ A(x)$可以预处理,然后数论分块计算

单次$ O(\sqrt{4000000})=O(2000)$

考虑修改

现在问题是:单点修改,区间求和

修改次数只有$ 10000$次,而求和次数达到$ 2*10^7$次

考虑分块

对于每个块我们维护块内前缀和以及前$ i$个块的和

这样查询是$ O(1)$的而修改是$ O(2000)$的

就以一种非常优秀的均摊复杂度解决了这道题


$ my \ code$

  1. #include<ctime>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<iostream>
  6. #include<algorithm>
  7. #include<queue>
  8. #define p 1000000007
  9. #define rt register int
  10. #define ll long long
  11. using namespace std;
  12. inline ll read(){
  13. ll x = ; char zf = ; char ch = getchar();
  14. while (ch != '-' && !isdigit(ch)) ch = getchar();
  15. if (ch == '-') zf = -, ch = getchar();
  16. while (isdigit(ch)) x = x * + ch - '', ch = getchar(); return x * zf;
  17. }
  18. void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
  19. void writeln(const ll y){write(y);putchar('\n');}
  20. int i,j,k,m,n,x,y,z,cnt,blo;
  21. int phi[],ss[],inv[],f[];bool pri[];
  22. int val[],qz1[][],qz2[];
  23. void init(int M){
  24. //mu[1]=1;
  25. phi[]=;blo=(int)sqrt(M);
  26. for(rt i=;i<=M;i++){
  27. if(!pri[i])phi[i]=i-,ss[++cnt]=i;
  28. for(rt j=;j<=cnt&&i*ss[j]<=M;j++){
  29. pri[i*ss[j]]=;
  30. phi[i*ss[j]]=phi[i]*phi[ss[j]];
  31. if(i%ss[j]==){
  32. phi[i*ss[j]]=phi[i]*ss[j];
  33. break;
  34. }
  35. }
  36. }
  37. for(rt i=;i<=M;i++)val[i]=(val[i-]+1ll*i*i%p*phi[i]%p)%p;
  38. for(rt i=;i<=M;i++){
  39. f[i]=1ll*i*i%p;
  40. if((i-)%blo==)qz1[(i-)/blo][]=f[i];
  41. else qz1[(i-)/blo][(i-)%blo]=(qz1[(i-)/blo][(i-)%blo-]+f[i])%p;
  42. }
  43. qz2[]=qz1[][blo-];
  44. for(rt i=;i<=blo;i++)qz2[i]=(qz2[i-]+qz1[i][blo-])%p;
  45. inv[]=inv[]=;
  46. for(rt i=;i<=M;i++)inv[i]=1ll*inv[p%i]*(p-p/i)%p;
  47. }
  48. int qz(int x){
  49. if(!x)return ;int ks=(x-)/blo;
  50. if(ks==)return qz1[][x-];
  51. else return (qz1[ks][(x-)%blo]+qz2[ks-])%p;
  52. }
  53. int calc(int n){
  54. int ans=;
  55. for(rt i=;i<=n;){
  56. int R=n/(n/i);
  57. (ans+=1ll*(qz(R)-qz(i-))*val[n/i]%p)%=p;
  58. i=R+;
  59. }
  60. return (ans+p)%p;
  61. }
  62. void update(int x,int y){
  63. int ks=(x-)/blo;
  64. for(rt i=x;(i-)%blo!=||i==x;i++)(qz1[ks][(i-)%blo]+=y)%=p;
  65. for(rt i=ks;i<=blo;i++)(qz2[i]+=y)%=p;
  66. (f[x]+=y)%=p;
  67. }
  68. int main(){
  69. n=read();m=read();
  70. init(m);
  71. for(rt i=;i<=n;i++){
  72. x=read();y=read();int v=read()%p;k=read();
  73. int gc=__gcd(x,y);
  74. v=1ll*v*inv[x]%p*inv[y]%p*gc%p*gc%p;
  75. update(gc,v-f[gc]);
  76. writeln(calc(k));
  77. }
  78. return ;
  79. }

Luogu P3700「CQOI2017」小Q的表格的更多相关文章

  1. 【LOJ】#3020. 「CQOI2017」小 Q 的表格

    #3020. 「CQOI2017」小 Q 的表格 这个的话求出来\(g = gcd(a,b)\) 会修改所有gcd为g的位置 我们要求\((g,g)\)这个位置的数一定是\(g^{2}\)的倍数 之后 ...

  2. 「NOI2013」小 Q 的修炼 解题报告

    「NOI2013」小 Q 的修炼 第一次完整的做出一个提答,花了半个晚上+一个上午+半个下午 总体来说太慢了 对于此题,我认为的难点是观察数据并猜测性质和读入操作 我隔一会就思考这个sb字符串读起来怎 ...

  3. 【CQOI2017】小Q的表格

    [CQOI2017]小Q的表格 稍加推导就会发现\(f(a,b)=a\cdot b\cdot h(gcd(a,b))\). 初始时\(h(n)=1\). 询问前\(k\)行\(k\)列时我们就反演: ...

  4. 洛咕 P3700 [CQOI2017]小Q的表格

    洛咕 P3700 [CQOI2017]小Q的表格 神仙题orz 首先推一下给的两个式子中的第二个 \(b\cdot F(a,a+b)=(a+b)\cdot F(a,b)\) 先简单的想,\(F(a,a ...

  5. loj #2008. 「SCOI2015」小凸想跑步

    #2008. 「SCOI2015」小凸想跑步   题目描述 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 n nn 边形,N NN 个顶点按照逆时针从 0∼n−1 0 ...

  6. loj #2006. 「SCOI2015」小凸玩矩阵

    #2006. 「SCOI2015」小凸玩矩阵   题目描述 小凸和小方是好朋友,小方给小凸一个 N×M N \times MN×M(N≤M N \leq MN≤M)的矩阵 A AA,要求小凸从其中选出 ...

  7. 「NOI2015」小园丁与老司机

    「NOI2015」小园丁与老司机 要不是这道码农题,去年就补完了NOI2015,其实两问都比较simple,但是写起来很恶心. 先解决第一问,记 \(dp[i]\) 表示老司机到达第 \(i\) 棵树 ...

  8. bzoj 4815: [Cqoi2017]小Q的表格 [数论]

    4815: [Cqoi2017]小Q的表格 题意: 单点修改,查询前缀正方形和.修改后要求满足条件f(a,b)=f(b,a), b×f(a,a+b)=(a+b)*f(a,b) 一开始sb了认为一次只会 ...

  9. 「SCOI2015」小凸想跑步 解题报告

    「SCOI2015」小凸想跑步 最开始以为和多边形的重心有关,后来发现多边形的重心没啥好玩的性质 实际上你把面积小于的不等式列出来,发现是一次的,那么就可以半平面交了 Code: #include & ...

随机推荐

  1. [luogu1503][鬼子进村]

    题目链接 思路 将哪些村庄已经被摧毁了放到treap里.查询的时候如果当前村庄已经被毁了,那么就可以直接输出0.不然就输出这个村庄的后继-前驱-1.原因显然 代码 #include<cstdio ...

  2. [luogu3388][割点]

    题目链接 思路 真板子题.割点是指在一个无向图中,删去之后图将不再连通的点.可以用tarjan算法求.根据割点有两种情况,一种是根,一种是非根.如果不是根的就去判断在tarjan的时候当前节点所能到的 ...

  3. Linux提取不匹配字符串的行和列(awk函数)

    如下图所示,想把含有‘-nan’字符串的行提取出来 则用到awk函数,命令行如下: awk '{if($3!="-nan"){print $3}}' CHB_vs_ITU.weir ...

  4. pytest 7 assert断言

    前言:断言是自动化最终的目的,一个用例没有断言,就失去了自动化测试的意义了. 断言用到的是 assert关键字.之前的介绍,有的测试方法中其实用到了assert断言.简单的来说,就是预期的结果去和实际 ...

  5. opencv mat裁剪

    主要记录的就是对Mat裁剪后,新Mat指向的内存和原来的Mat共用. OpenCV入门教程(3)-Mat类之选取图像局部区域

  6. Unity 光照着色器

    光照着色器需要考虑光照的分类,一般分为漫反射和镜面反射. 漫反射计算基本光照: float brightness=dot(normal,lightDir)    将法线和光的入射方向进行点积运算,求出 ...

  7. 关于串session

    关于session: 最近在用IE浏览器调试不同用户所拥有的权限功能,出现了串session.串session,主要的流程结构如下: 解决方法: 在IE快捷方式上点击鼠标右键>属性>快捷方 ...

  8. 【强大知名的CAD绘图工具】AutoCAD 2019 for Mac

    以上图片来源于互联网分享,如涉及版权问题请联系作者删除. 文章素材来源:风云社区(www.scoee.com) 下载地址:风云社区(www.scoee.com)   [简介] AutoCAD 2019 ...

  9. 转:值得收藏!那些鲜为人知的 Mac OS X 技巧

    看到一篇网友整理的比较好的“那些鲜为人知的 Mac OS X 技巧”,转载过来分享给大家!希望能有帮助. 更多专题,可关注小编[磨人的小妖精],查看我的文章,也可上[风云社区 SCOEE],查找和下载 ...

  10. 基于python调用libvirt API

    基于python调用libvirt API 1.程序代码 #!/usr/bin/python import libvirt import sys def createConnection(): con ...