求高效算法 -- 在线等

xinjieangel 2009-07-01 06:30:43


计算有没有重合端口

每个端口的计算方法是:basic+number*step
basic是基数
number是个数
step是步长如:
basic = 5000; number = 1000; step = 4;
这1000个端口所占用的端口号是:5000+4*n (n的取值是0到999)。即从5000开始,每加4为一个端口号。
第501个端口的端口号是:7000即5000+(501-1)*4

那么现在有两组basic,number,step,用高效的算法,得出是否有重合的端口。

请注意:高效,并不是用数去一个一个的比。
...全文
34 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
chuengchuenghq 2009-07-15
  • 打赏
  • 举报
回复
膜拜高财生
易之阴阳 2009-07-14
  • 打赏
  • 举报
回复
中国剩余定理,同余问题
或整数离散直线问题
step1=4
step2=3
4m-3n=25
m=(3/4)*n+25
只需把你的一组中的是4的倍数的个数代入,看有没有超出m 的范围
Yi_mii 2009-07-14
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 xinjieangel 的回复:]
鬼谷算法可以么?
完全没有看出来。

后来请教一朋友,他告诉我一个方法:
basic简为b
number简为n
step简为s
即:b2+n2*s2 - (b1+n1*s1) 的绝对值 与s1 进行取余,若为零,说明会出现相同的数值。

具体对错,我也搞不清楚,只有先用上,然后再进行测试了……

如有问题,还请各位指教。
[/Quote]

n1,n2是指number的最大值吗?
这种情况只是必要条件不是充分条件吧
Yi_mii 2009-07-14
  • 打赏
  • 举报
回复
找到n1,n2使下式成立即存在端口重合:
b1+n1*s1=b2+n2*s2 (b1,b2,s1,s2已知)

即式(1):(n1*s1)%s2=b2-b1 中未知数n1有整数解
上式等价 ((n1%s2)*(s1%s2))%s2=b2-b1
式(2): (y*(s1%s2))%s2=b2-b1 (设y=n1%s2, 0<=y<=s2-1,且为整数)
用式(2)在y的范围里遍历下就知道有没有重合端口了。

最大计算次数为 min(s1,s2,n1最大值,n2最大值) ...s比n大时遍历式(1)中的n

想不到更有效的了,式(2)解不出。。。
如果还是不高效,只能换端口分配算法了
Yi_mii 2009-07-14
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 liuzk423 的回复:]
中国剩余定理,同余问题
或整数离散直线问题
step1=4
step2=3
4m-3n=25
m=(3/4)*n+25
只需把你的一组中的是4的倍数的个数代入,看有没有超出m 的范围
[/Quote]
...............m=(3/4)*n+25/4
knate 2009-07-08
  • 打赏
  • 举报
回复

//复杂度大概为GCD(s1*n1,s2*n2)
#include <iostream>
#include <vector>

using namespace std;

int gcd(int a,int b){
if(a<b)
return gcd(b,a);
if(!(a%b))
return b;
else
return gcd(b,a%b);
}

int max(int a,int b){
return (a>b?a:b);
}

int main(){
int basic1(1000),step1(5),number1(15);
int basic2(1000),step2(15),number2(13);
int max_divisor=gcd(step1*number1,step2*number2);
int b,s,n;
int bt,st,nt;
vector<int> v_sum(0);
if(basic1>basic2){
b = basic1;
s = step1;
n = number1;
bt = basic2;
st = step2;
nt = number2;
}
else{
b = basic2;
s = step2;
n = number2;
bt = basic1;
st = step1;
nt = number2;
}
for(int sum = b;sum < b+s*n && sum < bt+max_divisor;sum += s){
if(!((sum-bt)%st) || !((sum-bt)%nt)){
v_sum.push_back(sum);
cout<<sum<<endl;
}
}
int first,end;
first = max(basic1,basic2);
end = max(basic1+step1*number1,basic2+step2*number2);
if(end<first)
cout<<"数量:"<<0<<endl;
else{
int x = 0;
for(vector<int>::iterator pfirst = v_sum.begin();(*pfirst <= (end-first)% max_divisor) && pfirst != v_sum.end();++pfirst){
++ x;
}
cout<<"数量:"<<x+v_sum.size()*((end-first)/max_divisor);
}

system("pause");
return 0;
}

jlp999 2009-07-03
  • 打赏
  • 举报
回复
#define UINT unsigned int 
#define METHOD(base, num, step) (base + (num - 1)*step)
#define SAME_PART_NUM(max, base, step) ((max - base)/step)

bool SameNum(UINT base1, UINT num1, UINT step1,
UINT base2, UINT num2, UINT step2)
{
UINT base2_same_part_num_max = 0;
UINT i = 0;

/* have same number part */
if ((base1 <= base2)
&& (METHOD(base1, num1, step1) >= base2))
{
/* (b2 + x*s2) == (b1 + y*s1) */
/* so, y = (b2 - b1 + x*s2)/s1 */
/* so, we use (0 == (b2 - b1 + x*s2)%s1) */
base2_same_part_num_max = SAME_PART_NUM(METHOD(base1, num1, step1) - base2)/step2;

for (i = 0; i <= base2_same_part_num_max, i++)
{
if (0 == (base2 - base1 + i*step2)%step1)
{
return true;
}
}

return false;
}
else
{
SameNum(base2, num2, step2, base1, num1, step1);
}
}


pangshaohua 2009-07-03
  • 打赏
  • 举报
回复
位图法
时间转换为空间算法
时间的复杂度为(1)
jlp999 2009-07-03
  • 打赏
  • 举报
回复
C code:

#define UINT unsigned int
#define METHOD(base, num, step) (base + (num - 1)*step)
#define SAME_PART_NUM(max, base, step) ((max - base)/step)

bool SameNum(UINT base1, UINT num1, UINT step1,
UINT base2, UINT num2, UINT step2)
{
UINT base2_same_part_num_max = 0;
UINT i = 0;

/* have same number part */
if ((base1 <= base2)
&& (METHOD(base1, num1, step1) >= base2))
{
/* (b2 + x*s2) == (b1 + y*s1) */
/* so, y = (b2 - b1 + x*s2)/s1 */
/* so, we use (0 == (b2 - b1 + x*s2)%s1) */
base2_same_part_num_max = SAME_PART_NUM(METHOD(base1, num1, step1) - base2)/step2;

for (i = 0; i <= base2_same_part_num_max, i++)
{
if (0 == (base2 - base1 + i*step2)%step1)
{
return true;
}
}

return false;
}
else
{
SameNum(base2, num2, step2, base1, num1, step1);
}
}
lasttimes 2009-07-03
  • 打赏
  • 举报
回复

C/C++ code
先试下发代码
showjim 2009-07-02
  • 打赏
  • 举报
回复
鬼谷算法可解此题
haggard_hunan 2009-07-02
  • 打赏
  • 举报
回复
basic1 + x * step1 = basic2 + y * step2

x y基实可以看作是同一个变量,只是自变量范围不同而已,其它都是常量。。。。。
xinjieangel 2009-07-02
  • 打赏
  • 举报
回复
[size=10px]一楼的遍历的方法就不考虑了,因为之前也是用的这个方法,但因为大量比较的时候,时间太长,所以被客户指了出来,二楼所述的,好像也用了大量的循环……

现在主要需要问题是范围的重合的部分,处理方法不太好,以前听人提过,用取余的方法,如果余数为0,则表示有重合,但用哪个数,取哪个的余,我就不知道了。我从上学时对那种公倍、公约、取余什么的相关算法就不大感冒,到今天也不清楚润年算法为什么那么做,所以,这个取余,我照旧是想不出来。

请各位高手指点一下,感激不尽。

下面是一些处理,缺少的是范围重合部分,请看一下:


if ((i_basic1 > (i_basic2 + i_step2 * i_number2))
|| (i_basic2 > (i_basic1 + i_step1 * i_number1))) {
return OK;
} else if ((i_step1 == i_step2) && ((i_basic1 % i_step1) != (i_basic2 % i_step1))) {
return OK;
} else {/* ??? */}

谢谢。
xinjieangel 2009-07-02
  • 打赏
  • 举报
回复
[size=10px]一楼的遍历的方法就不考虑了,因为之前也是用的这个方法,但因为大量比较的时候,时间太长,所以被客户指了出来,二楼所述的,好像也用了大量的循环……

现在主要需要问题是范围的重合的部分,处理方法不太好,以前听人提过,用取余的方法,如果余数为0,则表示有重合,但用哪个数,取哪个的余,我就不知道了。我从上学时对那种公倍、公约、取余什么的相关算法就不大感冒,到今天也不清楚润年算法为什么那么做,所以,这个取余,我照旧是想不出来。

请各位高手指点一下,感激不尽。

下面是一些处理,缺少的是范围重合部分,请看一下:


if ((i_basic1 > (i_basic2 + i_step2 * i_number2))
|| (i_basic2 > (i_basic1 + i_step1 * i_number1))) {
return OK;
} else if ((i_step1 == i_step2) && ((i_basic1 % i_step1) != (i_basic2 % i_step1))) {
return OK;
} else {/* ??? */}

谢谢。
GibGas 2009-07-02
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 xinjieangel 的回复:]
鬼谷算法可以么?
完全没有看出来。

后来请教一朋友,他告诉我一个方法:
basic简为b
number简为n
step简为s
即:b2+n2*s2 - (b1+n1*s1) 的绝对值 与s1 进行取余,若为零,说明会出现相同的数值。

具体对错,我也搞不清楚,只有先用上,然后再进行测试了……

如有问题,还请各位指教。
[/Quote]

didnt see how it would work....
let me give u a sample:

b1 = 4900, n1 = 1000, s1 = 7;
b2 = 4000, n2 = 500, s2 = 101;

with ur method: | b2+n2*s2 - (b1+n1*s1) | % s1(or s2) != 0, which means there is no duplicate.
BUT, what happens in port 5313?

well i also made a mistake above:

if( (step1*i + b) % step2 )
==> if( (step1*i + b) % step2 == 0 )
xinjieangel 2009-07-02
  • 打赏
  • 举报
回复
鬼谷算法可以么?
完全没有看出来。

后来请教一朋友,他告诉我一个方法:
basic简为b
number简为n
step简为s
即:b2+n2*s2 - (b1+n1*s1) 的绝对值 与s1 进行取余,若为零,说明会出现相同的数值。

具体对错,我也搞不清楚,只有先用上,然后再进行测试了……

如有问题,还请各位指教。
GibGas 2009-07-01
  • 打赏
  • 举报
回复
 
// input (basic1, number1, step1), (basic2, number2, step2)

// find the start and the end that we need to compare, in this case we have the least times of loop, not difficult to do so

int b = basic1 - basic2;
for(int i=start;i<ends;i++)
{
if( (step1*i + b) % step2 )
return false; // which means there is a dulplicate
else
continue; // no duplicate
}
return true;


the basic idea:

if there is a duplicate in port N, then:
N = basic1 + n1 * step1 = basic2 + n2 * step2
so we have:
n1 * step1 + basic1 - basic2 = n2 * step2;
also we know n2 must be integer:
(n1 * step1 + basic1 - basic2) % step2 = 0;


well i know this method is not too smart, since we should more focus on efficiency...
expecting better ideas!
lanytin 2009-07-01
  • 打赏
  • 举报
回复
声明一个数组,大小为两组最后一个端口的最大的端口数(也就是max(base+(number-1)*step)),
把两次端口数存入数组,第一次,从数组下标为0开始,小的base(min(base))这一组,以固定的step,相应数组位置值+1;第二次,从数组下表(max(base)-min(base))开始,以固定的step,相应的数组位置值+1;
遍历,如数组中有=2的元素,说明有重合的端口。

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧