[国家集训队]Banner

Description

LZN 搞完保送生考试,终于要回到信息组大家庭了,Chanxer 决定要好好地欢迎LZN,于是他在在操场上整齐地插了(M + 1) *(N + 1) 个标杆,形成了一个平面直角坐标系,左下角的标杆的坐标为(0; 0),右上角的标杆的坐标为(M;N),Chanxer 现在想要选择两个标杆作为端点连上横幅“ 机房欢迎你”。
可是,由于Chanxer 很农,他不希望横幅被其它的标杆拦住,因此他要求选择的两个标杆的连线不应该经过其它标杆,并且横幅的长度还应该在[L;R]以内。
现在Chanxer 想要知道他有多少种选法,注意,由于横幅的两面是一模一样的,所以选择的两个点没有起点终点之分,鉴于答案可能很大,而又不允许上交Python、Java 等语言的源代码,你只需要告诉他答案除以B 的余数是多
少就可以了。

Solution

假设第一个端点选择在$(0,0)$,那么另一个端点的位置$(i,j)$必须满足$gcd(i,j)=1$,否则横幅就会穿过别的杆子,所以题中所求为

令$f(x,i)=\sum_{j=1}^x[gcd(i,j)=1](n-j+1)$
\begin{equation}
\begin{aligned}
& \sum_{i=1}^{m}\sum_{j=1}^{n}\left [ l^{2}\leq i^{2}+j^{2}\leq r^{2} \right ] \left [ gcd(i,j)=1\right ](m-i+1)(n-j+1)\\
= & \sum_{i=1}^m\sum_{j=max(1,\sqrt{l^2-i^2})}^{min(n,\sqrt{r^2-i^2})}[gcd(i,j)=1](m-i+1)(n-j+1)\\
= & \sum_{i=1}^{m}(m-i+1)\sum_{j=max(1,\sqrt{l^2-i^2})}^{min(n,\sqrt{r^2-i^2})}[gcd(i,j)=1](n-j+1)\\
= & \sum_{i=1}^m (m-i+1) (f(min(n,\lfloor \sqrt{r^2-i^2} \rfloor,i)-f(max(1,\lceil \sqrt{l^2-i^2} \rceil -1),i)\\
\end{aligned}
\end{equation}

化简$f(x,i)$
\begin{equation}
\begin{aligned}
f(x,i)& =\sum_{d|i}\sum_{d|j}^x \mu(d)(n-j+1)\\
& = \sum_{d|i} \mu (d) \sum_{j=1}^{\lfloor \frac xd \rfloor}(n+1-jd)\\
& = \sum_{d|i} \mu (d) ((n+1)\lfloor \frac xd \rfloor - \sum_{j=1}^{\lfloor \frac xd \rfloor}jd)\\
& = \sum_{d|i} \mu (d) ((n+1)\lfloor \frac xd \rfloor - \frac{d \lfloor \frac xd \rfloor (\lfloor \frac xd \rfloor +1)}{2})
\end{aligned}
\end{equation}

之后胡搞就可以了,这道题线性筛跑得飞快,但是我用了质因数分解的怪方法,差点过不去

细节不多,挺简单的,也就写了4天

 

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
long long m,n,l,r,mod,ans,p[105];
inline long long read()
{
    long long f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+ch-'0';
        ch=getchar();
    }
    return f*w;
}
long long s(long long x)
{
    return x*(x+1)/2%mod;
}
long long cal(long long x)
{
    long long ret=0;
    for(long long i=0;i<=(1<<(p[0]))-1;i++)
    {
        long long temp=1,mu=1;
        for(long long j=0;j<p[0];j++)
            if(i&(1<<j))
            {
                temp*=p[j+1];
                mu*=-1;
            }
        if(temp>x)
            continue;
        (ret+=mu*(((x/temp)*(n+1)%mod-temp*s(x/temp)%mod+mod)%mod+mod)%mod+mod)%=mod;
    }
    return ret;
}
int main()
{
    m=read();
    n=read();
    l=read();
    r=read();
    mod=read();
    for(long long i=1;i<=m;i++)
    {
        long long temp=i,L=0,R=0;
        p[0]=0;
        for(long long j=2;j<=sqrt(i);j++)
            if(!(temp%j))
            {
                p[++p[0]]=j;
                while(!(temp%j))
                    temp/=j;
            }
        if(temp!=1)
            p[++p[0]]=temp;
        if(l>=i)
            L=max(1ll,(long long)ceil(sqrt(l*l-i*i)));
        else
            L=1;
        R=min(n,(long long)sqrt(r*r-i*i));
        if(L<=R)
            (ans+=(cal(R)-cal(L-1)+mod)%mod*(m-i+1)%mod*2%mod)%=mod;
    }
    if(l<=1)
        (ans+=n*(m+1)%mod+m*(n+1)%mod)%=mod;
    printf("%lld\n",ans);
    return 0;
}
Banner

 

posted @ 2020-07-19 09:27  QDK_Storm  阅读(196)  评论(0编辑  收藏  举报