codeforces Educational Codeforces Round 16 D. Two Arithmetic Progressions 扩展欧几里得

来源:互联网 发布:北京java培训机构 编辑:程序博客网 时间:2024/05/16 10:57

先用exgcd等式求k的通解 然后根绝函数的单调性确定可选整数的区间注意点很多有点恶心
然后求个数就行了
坑点是整数运算两个数相除 a/b 的结果为正返回小于等于结果的第一个数,结果为负返回大于等于结果的第一个数

//1 9 3 11 49 109#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cmath>#define lson i<<1#define rson (i<<1)+1#define LL long long#define pi acos(-1.0)#define mid (l+r)/2#define maxn 10000005using namespace std;LL x,y;LL e_gcd(LL a, LL b){    if(b==0)    {       x = 1;       y = 0;       return a;    }    LL ans = e_gcd(b,a%b);    LL t = x;    x = y;    y = t-a/b*y;    return ans;}  //求通解LL a1,b1,a2,b2,l,r;int main(){    scanf("%I64d %I64d %I64d %I64d %I64d %I64d", &a1, &b1, &a2, &b2, &l, &r);    //扩展欧几里得求通解    LL a = a1, b = -1 * a2;    LL GCD = e_gcd(a, b);    if((b2 - b1)%GCD != 0) printf("0\n");    else{        //求k左右边界        x *= (b2 - b1)/GCD;        LL add = b / GCD ;        add = abs(add);        if((l - b1) % a1==0) l = (l - b1) / a1;        else if(l - b1 >= 0)l = (l - b1) / a1 + 1;        else l = (l - b1) / a1 ;        if((r - b1) % a1==0) r = (r - b1) / a1;        else if(r - b1 >= 0)r = (r - b1) / a1;        else r = (r - b1) / a1 - 1;        //根据l>=0的条件刷新边界 且k>=0刷新边界        if(r < 0) { printf("0\n"); return 0; }        if(r * a1 + b1 - b2 < 0) { printf("0\n"); return 0;}        l = max(0ll, l);        if(l * a1 + b1 - b2 < 0)        {            if((b2 - b1) % a1 != 0) l = (b2 - b1) / a1 + 1;            else  l = (b2 - b1) / a1;        }        //求l,r内的解        l-=x;        r-=x;        l += (add - (l % add + add) % add) % add;        r -= (r % add + add) % add;        printf("%I64d\n", max(0ll, (r - l)/add + 1));    }    return 0;}
0 0
原创粉丝点击