USACO2012 March Gold Large Banner
来源:互联网 发布:淘宝中文国际版app 编辑:程序博客网 时间:2024/06/03 02:53
Description
Bessie is returning from a long trip abroad to the Isle of Guernsey, and Farmer John wants to mount a nice “Welcome Home” banner for her arrival. Farmer John’s field has integer dimensions M x N (1 <= M, N <= 100,000), and he has installed a post at every possible point in the field with integer coordinates (if we assign a coordinate system to the field so that (0,0) is in the lower-left corner and (M,N) is in the upper-right corner). Of these (M+1) * (N+1) points, Farmer John must pick two as the endpoints of the banner.
Farmer John, being the perfectionist that he is, insists that the banner must be completely straight. This means that, for the two posts he chooses, there cannot be any other post on the line segment that the banner will form between them. Additionally, Farmer John wants the banner to have length at least L and at most H (1 <= L <= H <= 150,000). Farmer John needs your help to figure out how many possible ways he can hang the banner. The banner is reversible, so switching the two endpoints of the banner counts as the same way to hang the banner. As this number may bevery large, Farmer John simply wants to know what it is modulo B (1 <= B <=1,000,000,000).
题目大意
给定一个
(N+1)∗(M+1) (1≤N≤M≤100,000 )的格点图,在任意两点之间连线构成线段,并满足条件:
1) 线段长度在[L,R] (1≤L≤R≤150,000 )范围内;
2) 线段中间不经过任何格点。
求不同的线段方案数(答案模B )。
Input
Line 1: Five space-separated integers: M, N, L, H and B.
Sample Input
2 2 1 3 100
Output
Line 1: One integer denoting the number of possible banners (modulo B).
Sample Output
28
挂Spylft大犇的讲解。
这样的题目一定要规划好枚举的方向,我们尝试先枚举两维。
因为这个图的左右是对称的,我们可以只考虑所有斜率>0的线段:根据这条,我们可以分出当线段与水平/竖直方向平行的情况来。显然,只有全部长度为1的线段满足要求,此时如果1在
我们还可以算出一个格点图内与当前枚举的线段相同的线段个数:将这条线段视作与横竖直线构成了一个
通过分析两个条件,我们可以知道一个符合要求的
#include <cmath>#include <cstdio>int gcd(int a,int b){return b?gcd(b,a%b):a;}int n,m,L,R,P;void solve(){ int ans=0; if(L<=1)ans=(1LL*(n+1)*m+1LL*(m+1)*n)%P; for(int x=1;x<=n;x++) for(int y=1;y<=m;y++){ double Len=sqrt(x*x+y*y); if(Len<L||Len>R||gcd(x,y)!=1)continue; ans=(ans+2LL*(n-x+1)*(m-y+1))%P; } printf("%d\n",ans);}int main(){ scanf("%d %d %d %d %d",&n,&m,&L,&R,&P); if(P==1){puts("0");return 0;} solve();}
那么显然只能枚举一维,另一维需要一些技术上的处理:
对于一个x,所有符合题意的y必须满足
#include <cmath>#include <cstdio>#include <algorithm>#include <vector>#define M 100005using namespace std;int gcd(int a,int b){return b?gcd(b,a%b):a;}int n,m,L,R,P;int Eachprime[M][6],ptop[M];void init(int n){ for(int i=2;i<=n;i++) if(!ptop[i]) for(int j=i;j<=n;j+=i) Eachprime[j][ptop[j]++]=i;}long long sqr(int x){return 1LL*x*x;}long long calc(int low,int high,int prim){ long long lo=(low+prim-1)/prim; long long hi=high/prim; return ((m+1)*(hi-lo+1)-prim*(hi*(hi+1)-lo*(lo-1))/2)%P;}void solve(){ init(n); int ans=0,mi=min(n,R); int low=L,high=min(R,m); for(int w=1;w<=mi;w++){ while(low-1&&sqr(low-1)+sqr(w)>=sqr(L))--low; while(high&&sqr(high)+sqr(w)>sqr(R))--high; if(low>high||low>m)continue; int Allprime=1<<ptop[w]; int tmp=0; for(int S=0;S<Allprime;S++){ int prim=1,p=1; for(int k=0;k<(int)ptop[w];k++) if(S&(1<<k))prim*=Eachprime[w][k],p=-p; tmp=(tmp+p*calc(low,high,prim))%P; } ans=(ans+1LL*(n-w+1)*tmp)%P; if(ans<0)ans+=P; } if(L<=1&&1<=R)ans=(2*ans+1LL*(n+1)*m+1LL*(m+1)*n)%P; else ans=2*ans%P; printf("%d\n",ans);}int main(){ scanf("%d %d %d %d %d",&n,&m,&L,&R,&P); if(P==1){puts("0");return 0;} solve();}
跟着上面的代码分析一下:
solve()
函数中的low
指针与high
指针:当枚举的x逐渐变大时,这两个指针指向的就是当斜边长在
init()
就是在处理出每个数的质因子,复杂度接近Allprime
部分则是在枚举因子的子集。来回跳动的p就是在判断是减去还是加上。
calc(int low,int high,int prim)
函数部分:新处理出的lo
和hi
指针表示在ans=(ans+1LL*(n-w+1)*tmp)%P
处理掉了。而横方向的计算就有些麻烦了。
假设当前处理的因子为2,根据下图可以看出当前情况的个数为
综上,本题总共的最坏复杂度是
- USACO2012 March Gold Large Banner
- USACO 2012 March Gold Large Banner
- USACO 2008 March Gold cowjog
- POJ 2393 USACO March Gold
- 【USACO 2011 March Gold】切蛋糕
- 【USACO 2013 March Gold】奶牛逃跑
- [USACO 2008 March Gold] 土地购买
- BSOJ: 3748 【USACO 2006 March Gold】Milk Team Select产奶比赛
- Banner
- banner
- Banner
- Banner
- Banner
- banner
- banner
- banner
- banner
- banner
- 《C++高效编程:内存与性能优化》第十二章:优化IO
- 使用java将搜狗词库.scel文件转化为.txt文件
- SSM_login
- 利用runtime实现UIAlertView的block回调
- WPF-Dispatcher
- USACO2012 March Gold Large Banner
- iOS- Xcode8更新后输出log日志关闭
- mxnet深度学习实战:跑自己的数据实验和一些问题总结
- java源码分析之集合框架Map 07
- IE11 F12不能用的问题
- Hadoop中命令行解释
- 谈谈MySQL的存储引擎
- Raft算法分析与理解
- Perl语言入门(13 perl调试程序)