题目大意
给出一个(n+1)*(m+1)的点阵,求有多少种选起点终点(无序点对)使得连线除起点终点外不经过其他点,且长度在给定区间内。
解题思路
观察可知枚举横向x纵向y长度即可求出长度,gcd(x,y)==1时成立,与坐标轴平行的特殊考虑。枚举x即可求出y的取值范围,发现可以算出x有多少取法,每个y对应的取法是等差数列,可以直接求和。
但是我们要求互质,分解枚举的x,发现不同质数的个数有限,可以使用容斥原理解决。
code
using namespace std;
LL const MxN=1e7;
LL N,M,L,R,B,Pri[20];
LL Calc(LL X,LL Y,LL Z){
return (X>Y)?0:1ll*(2*M-X-Y+2)*((Y-X)/Z+1)/2%B;
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%lld%lld%lld%lld%lld",&N,&M,&L,&R,&B);
LL Mx=Min(N,R),Ans=0,L1,R1,I;
Fo(i,1,Mx){
L1=(L>i)?ceil(sqrt(L*L-i*i)):1,R1=Min(M,(long long)(sqrt(R*R-i*i))),I=i; LL Mx=sqrt(i);Pri[0]=0;
Fo(j,2,Mx)if(I%j==0){
Pri[++Pri[0]]=j;
while(I%j==0)I/=j;
}
if(I!=1)Pri[++Pri[0]]=I;Mx=(1<<Pri[0])-1;
Fo(s,0,Mx){
LL S=s,D=1,Tag=1;
Fo(j,1,Pri[0]){
D=(S&1)?D*Pri[j]:D;
Tag=(S&1)?-Tag:Tag;
S>>=1;
}
Ans=(Ans+1ll*Tag*(N-i+1)*Calc(Max(1ll,ceil(1.0*L1/D))*D,R1/D*D,D))%B;
}
LL tt;
tt++;
}
Ans=(1ll*Ans*2+((L==1)?(1ll*N*(M+1)%B+1ll*(N+1)*M%B)%B:0))%B;
printf("%lld",(Ans+B)%B);
return 0;
}