Banner 统计

来源:互联网 发布:python web运维自动化 编辑:程序博客网 时间:2024/06/05 00:42

题目描述:

LZN 搞完保送生考试,终于要回到信息组大家庭了,Chanxer 决定要好好地欢迎LZN,于是他在在操场上整齐地插了(M + 1) *(N + 1) 个标杆,形成了一个平面直角坐标系,左下角的标杆的坐标为(0; 0),右上角的标杆的坐标为(M;N),Chanxer 现在想要选择两个标杆作为端点连上横幅“ 机房欢迎你”。

可是,由于Chanxer 很农,他不希望横幅被其它的标杆拦住,因此他要求选择的两个标杆的连线不应该经过其它标杆,并且横幅的长度还应该在[L;R]以内。

现在Chanxer 想要知道他有多少种选法,注意,由于横幅的两面是一模一样的,所以选择的两个点没有起点终点之分,鉴于答案可能很大,而又不允许上交Python、Java 等语言的源代码,你只需要告诉他答案除以B 的余数是多少就可以了。

题目分析:

我们设两个两个标杆横坐标的距离差为x,纵坐标的距离差为y。
我们把x=0和y=0的情况刨出来单算:
只有L<=1的时候,这两种情况才有答案,答案为n*(m+1)+m *(n+1)

剩下的就是:
这里写图片描述

解释一下这个式子的意思:枚举x和y,答案加上满足长度在范围内且连线不经其他过格点(即gcd(x,y)==1)的方案。
对于一对固定的x和y,它的在横向上最多可以取(m-x+1)个位置,在纵向上最多可以取(n-y+1)个位置,那么可选的方案就共有(m-x+1)*(n-y+1)种,但是这条线段可以向上倾斜也可以向下倾斜,所以答案要乘2。

我们只需要枚举x和y,当然如果暴力枚举的话肯定GG。
观察这个式子,可以观察出,x只需要枚举到min(m,R),而当x固定的时候,y只需要在区间[sqrt(L* L-x *x),sqrt(R *R-x *x) ]内枚举即可,即可以省掉长度范围的判断。
按照上述条件把原式进行变形:
这里写图片描述

我们设 l 为枚举y的下限,r为枚举y的上限。
于是问题转化成了,如何求:
这里写图片描述

即如何快速求出:
这里写图片描述
(lim和x是给定的)

这个时候可以利用莫比乌斯函数进行容斥,即该式可以转化为:
这里写图片描述
上面这个转化不懂的可以选择看看我的Zap的题解:
http://blog.csdn.net/todobe/article/details/60579910
也可以根据莫比乌斯函数求和的性质,只有gcd为1的时候莫比乌斯函数的和为1,其他时候都为0,乘上方案数相加之后恰好为所求答案。

这样我们只要用sqrt(x)的时间枚举x的约数,然后∑(d|y)(n-y+1)是可以O(1)算出的。
不会O(1)算的小伙伴看这里:
我们设一个临时变量t=lim/d(因为是要求lim范围内合法的y嘛)
这个t代表共有t个合法的y,分别为:d,2d,3d……td;
我们要求的就是把这些y分别带入(n-y+1)里面然后求和。
这样我们把常量(n+1)提出来,就是(n+1)* t +((1+t)* t /2)*d
这样就算出来了(你们看完之后是不是觉得写题解的人非常智障啊=。=)

时间复杂度O(nsqrt(n))
其实后面的部分也可以不用莫比乌斯函数来做,直接容斥也可以。
(但是本宝宝是蒟蒻T^T,只会这种)

注意:

在计算第二维的下限的时候要和1取一个max,因为0的情况你已经单算了,如果枚举的x(即我代码里的i)已经大于L的时候,它的下限直接设为1即可

代码如下:

#include <cstdio>#include <iostream>#include <cmath>#include <algorithm>#define N 120000using namespace std;typedef long long LL;inline LL sqr(LL x) { return x*x; }LL n,m,L,R,mod,ans;inline LL sum(LL x) { return (x*(x+1)>>1)%mod; }bool mark[N];LL pri[N],u[N];int top;void init(){    u[1]=1;    for(LL i=2;i<N;i++)    {        if(!mark[i])        {            pri[++top]=i;            u[i]=-1;        }        for(int j=1;j<=top && pri[j]*i<N;j++)        {            mark[i*pri[j]]=true;            if(i%pri[j]==0)            {                u[i*pri[j]]=0;                break;            }            u[i*pri[j]]=-u[i];        }    }}LL calc(LL lim,LL x){    LL ans=0;    LL t,i;    for(i=1;i*i<x;i++)    {        if(x%i==0)        {            t=lim/i;            ans+=(u[i]*((n+1)*t%mod-sum(t)*i%mod)+mod)%mod,ans%=mod;            t=lim/(x/i);            ans+=(u[x/i]*((n+1)*t%mod-sum(t)*(x/i)%mod)+mod)%mod,ans%=mod;        }    }    if(i*i==x)    {        t=lim/i;        ans+=(u[i]*((n+1)*t%mod-sum(t)*i%mod)+mod)%mod,ans%=mod;    }    return ans;}int main(){    init();    cin>>n>>m>>L>>R>>mod;    for(LL i=1;i<=min(m,R);i++)    {        LL l=i>L?1:max(1ll,LL(ceil(sqrt(sqr(L)-sqr(i)))));        LL r=min(n,LL(sqrt(sqr(R)-sqr(i))));        if(l<=r) ans+=(calc(r,i)-calc(l-1,i)+mod)%mod*(m-i+1)%mod*2%mod,ans%=mod;    }    if(L<=1) ans+=m*(n+1)%mod+n*(m+1)%mod,ans%=mod;    cout<<ans<<endl;    return 0;}
0 0
原创粉丝点击