SGU 106 The equation 翻译 题解

106. 等式
时间限制:0.5s
内存限制:4096KB
  对于等式ax+by+c=0,给出a,b,c,x1,x2,y1,y2,你必须要确定有多少个满足下面条件的整数对(x,y)存在,x1<=x<=x2,y1<=y<=y2。
输入:
  包含整数a,b,c,x1,x2,y1,y2,所有数的绝对值都不大于 108
输出:
  输出结果个数。
================================华丽的分割线 ================================
  首先,抱歉,四天前就翻译好了,现在才上交题解!实在没办法啊,好几个原因,第一,个人好奇心太强了!扩展欧几里德算法的原理一定要看懂,知道怎么证明才想动手,但是实在抱歉哈,还是有一些没看懂的地方……第二,SGU不给数据,错了不知道从哪里查起,确实麻烦!第三,SGU的怪编译器,在:
long long i;
scanf("%lld", &i);
  这样它就是不接受,第一个点就WA,但是按照网上一个人的代码,改成:
long long i;
scanf("%I64d", &i);
  就AC了……无语吧,GCC我真没印象有I64d这玩意儿,就算有,是我才学疏浅,但是,但是……lld分明是C99中实用的,不信去《C Primer Plus》里去看!!
================================华丽的分割线 ================================
  算法分析,这题用到了 扩展欧几里德原理
  关于扩展的分析看上面的链接吧,接着简单分析一下,题意很清晰!直接贴思路:
  • 当a==0,b==0时,c若等于0则答案就是题目的范围内的所有整数点。
  • 若a==0时,by=-c,c是b的倍数,且在范围内就有答案,否则0个。
  • 当b==0时,ax=-c,c是a的倍数,且在范围内就有答案,否则0个。
  • 如果上面的条件都不符合,则使用扩展欧几里德算法。
 
   
#include < stdio.h >
#include
< stddef.h >
#include
< stdlib.h >
long long a, b, c;

long long extgcd( long long a, long long b, long long * x, long long * y)
{
int t, s;
if (b == 0 ){
* x = 1 ;
* y = 10 ;
return a;
}
t
= extgcd(b, a % b, x, y);
s
= * x;
* x = * y;
* y = s - a / b * ( * y);
return t;
}
#define max(a, b) ((a)>(b)?(a):(b))
#define min(a, b) ((a)<(b)?(a):(b))
#define swap(a, b) (a)^=(b);(b)^=(a);(a)^=(b);

int main( int argc, char ** argv)
{
long long x1, x2;
long long y1, y2;
long long x, y, t;
long long ans = 0 ;
//
scanf ( " %I64d%I64d%I64d " , & a, & b, & c);
c
= - c;
scanf (
" %I64d%I64d%I64d%I64d " , & x1, & x2, & y1, & y2);
// scanf("%d%d%d", &a, &b, &c);
// scanf("%d%d", &x1, &x2);
// scanf("%I64d%d", &y1, &y2);
// c = -c;
if (a == 0 && b == 0 ){
if (c == 0 ){
ans
= (x2 - x1 + 1 ) * (y2 - y1 + 1 );
}
}
else if (a == 0 ){
if (c % b == 0 && c / b >= y1 && c / b <= y2){
ans
= x2 - x1 + 1 ;
}
}
else if (b == 0 ){
if (c % a == 0 && c / a >= x1 && c / a <= x2){
ans
= y2 - y1 + 1 ;
}
}
else {
t
= extgcd(a, b, & x, & y);
if (c % t == 0 ){
x
*= c / t;
y
*= c / t;
// printf("%d %d\n", x, y);
long long lx, ly;
long long rx, ry;
lx
= (x1 <= x || (x1 - x) * t % b == 0 ) ? ((x1 - x) * t / b) : ((x1 - x) * t / b + 1 );
rx
= (x2 >= x || (x2 - x) * t % b == 0 ) ? ((x2 - x) * t / b) : ((x2 - x) * t / b - 1 );
ly
= (y1 <= y || (y - y1) * t % a == 0 ) ? ((y - y1) * t / a) : ((y - y1) * t / a - 1 );
ry
= (y2 >= y || (y - y2) * t % a == 0 ) ? ((y - y2) * t / a) : ((y - y2) * t / a + 1 );
if (lx > rx){
swap(lx, rx);
}
if (ly > ry){
swap(ly, ry);
}
// printf("%d %d %d %d\n", lx, rx, ly, ry);
if (ry >= lx && rx >= ly){
ans
= min(rx, ry) - max(lx, ly) + 1 ;
}
}
}
printf(
" %I64d\n " , ans);
return 0 ;
}

转载于:https://www.cnblogs.com/yylogo/archive/2011/06/06/SGU-106.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值