51nod 1132 覆盖数字的数量 V2

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;
}

时间: 2024-10-10 22:21:04

51nod 1132 覆盖数字的数量 V2的相关文章

51nod 1770 数数字

1770 数数字 基准时间限制:1 秒 空间限制:262144 KB 分值: 20 难度:3级算法题  收藏  关注 统计一下 aaa ? aaan个a × b 的结果里面有多少个数字d,a,b,d均为一位数. 样例解释: 3333333333*3=9999999999,里面有10个9. Input 多组测试数据. 第一行有一个整数T,表示测试数据的数目.(1≤T≤5000) 接下来有T行,每一行表示一组测试数据,有4个整数a,b,d,n. (1≤a,b≤9,0≤d≤

ACM学习历程—51NOD 1770数数字(循环节)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1770 这是这次BSG白山极客挑战赛的A题.由于数字全部相同,乘上b必然会有循环节,于是模拟乘法,记录数据,出现循环就退出即可. 代码: #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring>

51Nod - 1385 凑数字

51Nod - 1385 如果是n位数,x1 x2 x3 ... xn 从1到n的所有数中位数n-1的数字一定含有 1111...11,2222...22,...,9999...99 对于0 考虑n位数1000...00 其中有n-1个0 那么n-1位数中0-9都应该有n-1个(ans += 10*(n-1)) 考虑第一位数x1需要1, 2, 3, ..., x1(ans += x1) 但是如果第一位数大于第二位数 比如21 这时2最多出现一次,以为最高位出现时, 它的下一位不能出现2, 但是如

51nod 1084 矩阵取数问题 V2

1084 矩阵取数问题 V2 基准时间限制:2 秒 空间限制:131072 KB 一个M*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,先从左上走到右下,再从右下走到左上.第1遍时只能向下和向右走,第2遍时只能向上和向左走.两次如果经过同一个格子,则该格子的奖励只计算一次,求能够获得的最大价值. 例如:3 * 3的方格. 1 3 3 2 1 3 2 2 1 能够获得的最大价值为:17.1 -> 3 -> 3 -> 3 -> 1 -> 2 -> 2 -&g

51nod 1276 1276 岛屿的数量 (很好玩的题目

题意: 有N个岛连在一起形成了一个大的岛屿,如果海平面上升超过某些岛的高度时,则这个岛会被淹没.原本的大岛屿则会分为多个小岛屿,如果海平面一直上升,则所有岛都会被淹没在水下. 给出N个岛的高度.然后有Q个查询,每个查询给出一个海平面的高度H,问当海平面高度达到H时,海上共有多少个岛屿.例如: 岛屿的高度为:{2, 1, 3, 2, 3}, 查询为:{0, 1, 3, 2}. 当海面高度为0时,所有的岛形成了1个岛屿. 当海面高度为1时,岛1会被淹没,总共有2个岛屿{2} {3, 2, 3}. 当

51nod 1218 最长递增子序列 V2(dp + 思维)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1218 题解:先要确定这些点是不是属于最长递增序列然后再确定这些数在最长递增序列中出现的次数,如果大于1次显然是可能出现只出现1次肯定是必然出现.那么就是怎么判断是不是属于最长递增序列,这个只要顺着求一下最长递增标一下该点属于长度几然后再逆着求一下最长递减标一下该点属于长度几如果两个下标之和等于最长长度+1那么该点就属于最长递增序列,然后就是求1-len(le

51nod 1053 最大M子段和 V2

N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的.如果M >= N个数中正数的个数,那么输出所有正数的和. 例如:-2 11 -4 13 -5 6 -2,分为2段,11 -4 13一段,6一段,和为26. 收起 输入 第1行:2个数N和M,中间用空格分隔.N为整数的个数,M为划分为多少段.(2 <= N , M <= 50000) 第2 - N+1行:N个整数(-10^9 <= a[i] <= 10^

51nod 1590 合并数字

1590 合并数字 STL - List 练习题, 直接用 List 模拟题意即可,或者手写链表也行. #include <bits/stdc++.h> using namespace std; const int N = 1e4 + 10; list<int> List[N]; int main(){ int n,x,y,y_idx,x_idx; cin >> n ; for(int i = 1;i <= n; ++i){//初始化全为 i List[i].pu

51Nod 1006 1276 岛屿的数量

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 using namespace std; 7 8 const int MAXN = 5e4+5; 9 struct node 10 { 11 int pos, val; 12 }; 13 node a[MAXN], q[MAXN];