码迷,mamicode.com
首页 > 其他好文 > 详细

51nod 1132 覆盖数字的数量 V2

时间:2017-08-18 13:37:27      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:show   pen   lld   重复   tar   alt   整数   onclick   ++   

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1132

题意是给定a,b,l,r求[l,r]内有几个整数可以表示成ax+by(x,y为非负整数)。

直接算l<=ax+by<=r会重复计算一个数的多种表示方法,而两种表示方法(x,y)总是相差k*(b,-a),因此限制y取最小值进行去重

即x>=0,y>=0,l<=ax+by<=r,y<a/gcd(a,b)五个半平面的交的整点个数,可以分类一下然后用类欧几里德算法计算。

技术分享
#include<stdio.h>
typedef __int128 i64;
i64 f(i64 a,i64 b,i64 c,i64 n){
    if(!a||n<0)return 0;
    i64 s=0;
    if(a>=c)s+=a/c*(n+1)*n/2,a%=c;
    if(b>=c)s+=b/c*(n+1),b%=c;
    i64 m=(a*n+b)/c;
    return s+n*m-f(c,c-b-1,a,m-1);
}
i64 gcd(i64 a,i64 b){
    for(i64 c;b;c=a,a=b,b=c%b);
    return a;
}
i64 g(i64 a,i64 b,i64 c){
    c+=b;
    return f(a,c%a,b,c/a);
}
i64 cal(i64 a,i64 b,i64 c){
    i64 z=a/gcd(a,b)-1;
    if(b*z>c)return g(a,b,c);
    i64 p=(c-b*z)/a+1;
    return p*(z+1)+g(a,b,c-a*p);
}
int main(){
    int T;
    long long a,b,x,y;
    for(scanf("%d",&T);T;--T){
        scanf("%lld%lld%lld%lld",&a,&b,&x,&y);
        i64 ans=cal(a,b,y)-cal(a,b,x-1);
        int ss[100],sp=0;
        do ss[++sp]=ans%10+48;while(ans/=10);
        while(sp)putchar(ss[sp--]);
        putchar(10);
    }
    return 0;
}
View Code

 

51nod 1132 覆盖数字的数量 V2

标签:show   pen   lld   重复   tar   alt   整数   onclick   ++   

原文地址:http://www.cnblogs.com/ccz181078/p/7389056.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!