【国家集训队2013模拟】Banner

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值