题目大意

http://codeforces.com/contest/449/problem/E
给定一个N*M的网格。对一个顶点为格点的正方形R(不一定与格线平行),计算出其中有多少个单位格被R完全包含(记作F(R))。求所有正方形的F(R)之和。

题解

首先画一个“勾股图”:
粉色是我们的正方形(不和格线平行),设其外接正方形的边长为L,四周直角三角形的短边为a,则长边为L-a。设其中完整包含了F(L,a)个单位格。
可以发现,其中完全包含的单位正方形分成两部分:第一部分是中间小正方形里的个,第二部分是周边直角三角形里包含的。
我们这么计算第二部分:一红一白两个直角三角形拼成的矩形内有(L-a)*a个单位格,而对角线穿过了L-gcd(L,a)格,再除以2,就得到了一个三角形内的单位格数。将其乘以4,总共加起来得到:
没错,“斜线下方的格点数”没有简单公式,但“单位格数”有!
可以发现,F(L,a)即使当a>L-a时也成立,所以我们可以直接用a枚举到底,整道题目的答案就是:
我们把展开:
这分成两部分:第一部分是一个关于L的多项式,第二部分是gcd(L,a)的前缀和。
可以想象,也是如此分成两部分:第一部分是一个关于L的多项式(确切地说,是5次多项式),第二部分也是一个关于L的“多项式”,但其“未知数项”不是这种形式,而是这种形式。
至于怎么得到这个多项式呢,如果你数学好可以手推……作为一名数学技能荒废一年的咸鱼选手,我就直接用vector当低配版多项式类,让电脑推了……
不要忘了,我们要求的是上面那个玩意的前缀和。因此,只需要求出来这两种形式关于L的“前缀和”,然后乘以多项式中相应的系数,就可以完成任务。
前者很简单:L不超过10^6,暴力递推即可。后者也差不多,只需要先递推出来phi函数,然后枚举gcd(a,L)的值,就可以把Σgcd的表都打出来,详见代码。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
typedef vector<LL> Poly;
const LL MOD=1000000007;
const int H=6;
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);
}
LL lcm(LL a,LL b){return a*b/gcd(a,b);
}
LL quickpow(LL a,LL n){LL ans=1;while(n){if(n&1) ans=(ans*a)%MOD;a=(a*a)%MOD;n>>=1;}return ans;
}
LL inverse(LL a){return quickpow(a,MOD-2);
}
void print(Poly a){for(int i=0;i<a.size();i++){cout<<a[i]<<" ";}cout<<endl;
}
Poly operator * (Poly a,LL b){for(int i=0;i<a.size();i++){a[i]*=b;a[i]%=MOD;}return a;
}
Poly operator / (Poly a,LL b){return a*inverse(b);
}
Poly operator + (Poly a,Poly b){Poly c;int n=max(a.size(),b.size());c.resize(n);for(int i=0;i<a.size();i++){c[i]+=a[i];c[i]%=MOD;}for(int i=0;i<b.size();i++){c[i]+=b[i];c[i]%=MOD;}return c;
}
Poly operator * (Poly a,Poly b){Poly c;c.resize(a.size()+b.size()-1);for(int i=0;i<a.size();i++){for(int j=0;j<b.size();j++){c[i+j]+=a[i]*b[j]%MOD;c[i+j]%=MOD;}}return c;
}
const int SIZEN=1000010;
LL calc_presum_with(Poly a,LL ps[]){LL ans=0;for(int i=0;i<a.size();i++){ans+=(a[i]*ps[i])%MOD;ans%=MOD;}return ans;
}
Poly give_Fsum_L(void){//the component without gcdstatic LL A[10];A[0]=1;Poly ans(A,A+1);A[0]=0,A[1]=1;ans=ans*Poly(A,A+2);A[0]=1,A[1]=1;ans=ans*Poly(A,A+2);A[0]=1,A[1]=2;ans=ans*Poly(A,A+2);ans=ans/3;A[0]=0,A[1]=0,A[2]=-3;ans=ans+Poly(A,A+3);return ans;
}
LL G[SIZEN]={0};
LL phi[SIZEN];
LL P[SIZEN][H],PG[SIZEN][H];
void work(LL N,LL M){static LL A[10]; if(N>M) swap(N,M);//N是较小者A[0]=M+1,A[1]=-1;Poly D(A,A+2);A[0]=N+1,A[1]=-1;D=D*Poly(A,A+2);Poly F=give_Fsum_L();Poly F1=D*F;LL ans=0;ans+=calc_presum_with(F1,P[N]);ans%=MOD;A[0]=2;Poly F2=D*Poly(A,A+1);ans+=calc_presum_with(F2,PG[N]);ans%=MOD;ans=(ans+MOD)%MOD;printf("%I64d\n",ans);
}
void prepare(void){for(int i=1;i<SIZEN;i++){//精妙的求phi方法 phi[i]+=i;for(int j=i+i;j<SIZEN;j+=i){phi[j]-=phi[i];}}for(int g=1;g<SIZEN;g++){//求gcd(x,i)的前缀和 G[g]+=g;G[g]%=MOD;for(int x=2*g,d=2;x<SIZEN;x+=g,d++){G[x]+=(g*phi[d]%MOD);G[x]%=MOD;}}for(int i=0;i<H;i++){P[0][i]=PG[0][i]=0;}for(LL x=1;x<SIZEN;x++){LL p=1;for(int i=0;i<H;i++){P[x][i]=(P[x-1][i]+p)%MOD;PG[x][i]=(PG[x-1][i]+(p*G[x])%MOD)%MOD;p=(p*x)%MOD;}}
}
int main(){prepare();LL T,N,M;scanf("%I64d",&T);while(T--){scanf("%I64d%I64d",&N,&M);work(N,M);}return 0;
}

CF 449E Jzzhu and Squares解题报告相关推荐

  1. codeforces 450B. Jzzhu and Sequences 解题报告

    题目链接:http://codeforces.com/problemset/problem/450/B 题目意思:给出 f1 和 f2 的值,以及n,根据公式:fi = fi-1 + fi+1,求出f ...

  2. 【解题报告】博弈专场 (CF 2000~2200)前五题

    [解题报告]博弈专场 (CF 2000+)前五题 A:Fox and Card Game | CF388C 题意 思路 代码 B:Berzerk | CF786A 题意 思路 代码 C:Ithea P ...

  3. 【解题报告】CF DIV3 #ROUND 734 A~D1

    [解题报告]CF DIV2 #ROUND 707 A~D 比赛链接 比赛评价: 一般性,有段时间没打了,甚至忘记多组输入hh.顺便吐槽一下翻译软件确实不行,以后还是直接看英文好了 A. Polycar ...

  4. 【解题报告】CF DIV2 #ROUND 723 A~D

    [解题报告]CF DIV2 #ROUND 723 A~D 比赛链接 比赛评价: 发现这场十点就开了,然后就和ph巨佬一起玩了一场.我两分别再A和B罚时罚飞了,索性后面把C1,C2整出来了 排名2500 ...

  5. 【解题报告】随便练练二(CF 2300)

    [解题报告]随便练练二(CF 2300) A:Antimatter | CF383D 题意 思路 :DP 代码 B:Physical Education Lessons | CF915E 题意 思路一 ...

  6. 解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  7. 【解题报告系列】超高质量题单 + 题解(ACM / OI)超高质量题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我新写的超高质量的题解和代码,题目难度不 ...

  8. 解题报告(三)多项式求值与插值(拉格朗日插值)(ACM / OI)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  9. 解题报告(十三)中国剩余定理(ACM / OI)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  10. 解题报告(四)生成函数(ACM/ OI)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

最新文章

  1. 如何去重一个Oracle表
  2. 超图js版本在地图上使用图标标记地理点
  3. 图Graph--农夫过河问题(BFS/DFS应用)
  4. date.gethour_Java LocalDateTime类| 带示例的getHour()方法
  5. 新浪uc2010免费下载
  6. 在plist文件中增删改查
  7. docker cp :用于容器与主机之间的数据拷贝
  8. linux查进程内存问题,关于linux下内存问题排查的工具
  9. tensorflow使用object detection实现目标检测超详细全流程(视频+图像集检测)
  10. 挖掘频繁项集之FP-Growth算法
  11. 第一台全自动电子计算机,关于世界上第一台电子计算机ENIAC的叙述错误的是() senny全自动微电脑水位控制仪...
  12. fatal: unable to access 'https://github.com:***' 或者本机ping不通github.com解决方法
  13. hadoop put命令的格式_Hadoop Shell命令(基于linux操作系统上传下载文件到hdfs文件系统基本命令学习)...
  14. 快门速度、光圈、ISO(感光度)
  15. Unity 模拟投影器(Projector Simulator)
  16. reduceByKey中的加号是什么意思
  17. Java面向对象设计(面向对象)
  18. [linux] linux sed命令删除一行/多行
  19. 编程-----魔法币投币方案设计
  20. 微软Office 2013定价及版本详情曝光

热门文章

  1. 51系列单片机IO模试设置
  2. 百度糯米用大数据重塑O2O产业
  3. 在简历中使用STAR法则
  4. PS制作火焰效果文字的方法步骤教程
  5. 数值微分的python实现
  6. matlab求解整数规划问题
  7. JS字符串前补位和后补位
  8. app store android退款,买完 App、游戏内购就后悔了?手把手教你如何申请 App Store 退款...
  9. c语言1076素数,九度OJ 1076:N的阶乘 题解
  10. 炫酷的动态粒子背景效果(vue专属)