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;}
- Banner 统计
- Banner
- banner
- Banner
- Banner
- Banner
- banner
- banner
- banner
- banner
- banner
- Banner
- banner
- Banner
- banner
- Banner
- Banner
- Banner
- 数组法求C++大数的序列和
- Android Studio 更新第三方.so
- 红蓝牌
- 奇怪的比赛,蓝桥杯2012年第4题
- Jsch学习
- Banner 统计
- [构造] Codeforces 618F Wunder Fund Round 2016 F. Double Knapsack
- 蓝桥杯第五届省赛C/C++A组第五题 锦标赛
- 快速实现python c扩展模块
- kubernetes calico网络qos设计
- 向后兼容--对象检测
- hdu 4508 湫湫系列故事——减肥记I (最简单的完全背包)
- 蓝桥杯——网络寻路(dfs)
- 二叉树的前序遍历