51nod-1131 覆盖数字的数量

原题链接

基准时间限制:1 秒 空间限制:131072 KB 分值: 80  难度:5级算法题
 收藏
 关注
给出一段从A - B的区间S(A,B为整数),这段区间内的整数可以随便使用任意次。再给出一段从X - Y的区间T,问用区间S中的整数做加法,可以覆盖区间T中多少个不同的整数。
例如:区间S为8 - 10,区间T为3 - 20。在3 - 20中,整数8(8),9(9),10(10),16(8+8),17(8+9),18(9+9),19(9+10),20(10+10)。可以被区间S中的数覆盖,因此输出8。
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 1000)
第2 - T + 1行:每行4个数:A, B , X, Y,中间用空格分隔。(1 <= A < B <= 10^18, 1 <= X < Y <= 10^18)
Output
输出共T行,每行1个数,区间[X,Y]中可以由A-B中的整数相加得到的不同整数的数量。
Input示例
1
8 10 3 20
Output示例
8
在[x, y]中用ka进行划分阶段,已知ka和(k+1)a在[x, y]区间中,现在只要判断ka < z < (k+1)a中有多少个数被覆盖即可,因为a到b连续,所以ka到kb全被覆盖,所以只需判断kb和(k+1)a的大小关系即可

#include <bits/stdc++.h>
#define MOD 1000000007
#define maxn 505
#define INF 1e18
using namespace std;
typedef long long ll;

ll a, b, x, y;
ll solve1(ll k, ll c){
	
	ll d;
	if((b - a) > INF / k)
	 d = INF;
	else
	 d = (b - a) * k;
	if(d >= a - 1)
	 d = a - 1;
	ll e = c - k * a;
	if(d >= e) {
		return d - e + 1;
	} 
	return 0;
}
ll solve2(ll k, ll c){
	ll d;
	if((b - a) > INF / k)
	 d = INF;
	else
	 d = (b - a) * k;
    if(d >= c - k * a)
     d = c - k * a;
    return d + 1;
}
ll solve3(ll k1, ll k2){
	
	k1++;
	k2--;
	ll e = a - 1;
	ll h = e / (b - a);
	if(k1 > h)
	 return (k2 - k1 + 1) * a;
	if(k1 >= h && k1 < k2)
		return (k2 - k1) * a + (h * (b - a) + 1 + k1 * (b - a) + 1) * (k1 - h + 1) / 2;  
	if(h >= k2)
	 return (k1 * (b - a) + 1 + k2 * (b - a) + 1) * (k2 - k1 + 1) / 2;
}
int main(){
	
	//freopen("in.txt", "r", stdin);
	int t;
	scanf("%d", &t);
	while(t--){
		scanf("%I64d%I64d%I64d%I64d", &a, &b, &x, &y);
		if(x < a)
		 x = a; 
		if(a > y)
		 puts("0");
		else{
			ll k1 = x / a;
			ll k2 = y / a;
			if(k1 == k2){
				ll d;
				if((b - a) > INF / k1)
				 d = INF;
				else
				 d = (b - a) * k1;
				x -= k1 * a;
				y -= k2 * a;
				if(d < x)
				 puts("0");
				else{
					if(d >= y)
					 d = y;
					printf("%I64d\n", d - x + 1);
				}
			}
			else{
				ll ans = 0;
				ans += solve1(k1, x);
				ans += solve2(k2, y);
				if(k2 - k1 > 1)
				 ans += solve3(k1, k2); 
				printf("%I64d\n", ans);
			} 
		}
	}
	return 0;	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值