【国家集训队2013模拟】Banner

来源:互联网 发布:js调用摄像头拍照 编辑:程序博客网 时间:2024/05/01 12:40

Description

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

Solution

题意是

i=1nj=1m(ll<=ii+jj<=rr,gcd(i,j)=1)(ni+1)(mi+1)

(i,j都是长度)
我们枚举i之后,根据范围枚举j
i=1n(ni+1)j=max(1,llii)min(m,rrii)(l>i,>,gcd(i,j)=1)(mi+1)

我们要找的是互质的,那么我们可以用总数减去不互质的
i=1n(ni+1)(suan(rrii)suan(llii1))

我们的suan(x)就是计算1到x里面与x互质的答案
用容斥原理暴力处理就好了。
注意c++里面位运算得优先级,非常低。

Code

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)typedef long long ll;const int maxn=100;using namespace std;ll i,j,k,l,t,n,m,mo,r,a[maxn];ll ans;ll sqr(ll x){    return x*x;}ll chuli(ll x){    return x*(x+1)/2%mo;}ll suan(ll x){    ll i,j;    ll w=((m+1)*x%mo-chuli(x)+mo)%mo;    fo(i,1,(1<<a[0])-1){        ll o=1,p=1;        fo(j,1,a[0]){            if((i&(1<<(j-1))))p*=a[j],o=-o;        }        if(p>x)continue;        w=(w+o*(((m+1)*(x/p)%mo-chuli(x/p)*p%mo+mo)%mo+mo))%mo;    }    return w;}int main(){    scanf("%lld%lld%lld%lld%lld",&n,&m,&l,&r,&mo);    fo(i,1,min(n,r)){        a[0]=0;t=i;        fo(j,2,sqrt(i)){            if(t%j==0){                a[++a[0]]=j;                while(t%j==0)t=t/j;            }        }        if(t!=1)a[++a[0]]=t;        if(l>=i)k=max(ll(1),ll(ceil(sqrt(sqr(l)-sqr(i)))));else k=1;        t=min(m,ll(sqrt(sqr(r)-sqr(i))));        if(k<=t)ans=(ans+(suan(t)-suan(k-1)+mo)%mo*(n-i+1)%mo*2%mo)%mo;    }    if(l<=1){        ans=(ans+m*(n+1)%mo+n*(m+1)%mo)%mo;    }    printf("%lld\n",ans);}
1 0
原创粉丝点击