java乘法表倒着顺序_java – 如果按顺序放置NxM乘法表,那么中间的数字是多少?...

如果我有一个乘法表大小,例如,3×5:

1 2 3 4 5

2 4 6 8 10

3 6 9 12 15

我把所有这些数字按顺序排列:

1 2 2 3 3 4 4 5 6 6 8 9 10 12 15

中间的数字是多少?在这种情况下,它是5.

N和M总是奇数,所以只能有一个答案.

对此有快速解决方案吗?我正在寻找O(N log NM)之间的东西

这是各种各样的功课,但我真的迷失了这个.我想出了一些想法,但它们都有一些缺点:

public class Table {

public static void main(String[] ar) {

Scanner scanner = new Scanner(System.in);

int w = scanner.nextInt();

int h = scanner.nextInt();

int[] s = new int[w * h + 1];

for (int i = 1; i <= w; i++)

for (int j = 1; j <= h; j++)

s[i * j] = s[i * j] + 1;

int sum = 0;

for (int i = 0; i < s.length; i++) {

sum += s[i];

if (sum >= s.length / 2) {

System.out.println(i);

break;

}

}

}

}

这足以足够快地解决大多数测试(<4s),但是对于大N和M,超出了存储器限制(我不知道确切的限制). 我们的想法是跟踪每个数字的出现次数,然后按顺序遍历所有数字,添加每次迭代的出现次数.当出现次数大于或等于w * h / 2时,它是中间的数字并打印出来.

public class Table {

public static void main(String[] ar) {

Scanner scanner = new Scanner(System.in);

int w = scanner.nextInt();

int h = scanner.nextInt();

int sum = 0;

for (int i = 1; i <= w * h; i++) {

for (int j = 1; j <= Math.sqrt(i); j++) {

if (i % j == 0) {

int k = i / j;

if (k <= w && k != j) sum++;

if (k <= h && k != j) sum++;

if (k <= w && k <= h && k == j) sum++;

}

}

if (sum >= (w * h + 1) / 2) {

System.out.println(i);

break;

}

}

}

}

试图克服内存限制,我尝试计算每个数字的出现,直到它们来到中间.我注意到每个数字的乘法表中出现的次数是它们拥有的因子数.

不够快.

任何人都可以想出任何指针吗?我知道在建议的O(N log NM)解决方案中使用了二进制搜索.

1 <= N <= 10^5

1 <= M <= 10^5

解!

好的,感谢@PeterdeRivaz我能够找到并实现我的问题的解决方案.这个想法就像他描述的那样,这是实际的实现:

public class Kertotaulu {

public static void main(String[] ar) {

Scanner scanner = new Scanner(System.in);

long h = scanner.nextLong();

long w = scanner.nextLong();

long min = 1;

long max = w*h;

long mid = 0;

while (min <= max) {

mid = (min + max) / 2;

long sum = 0;

for (int i = 1; i <= h; i++) sum += Math.min(mid / i, w);

sum--;

if (sum < (w * h) / 2) min = mid + 1;

else if (sum > (w * h) / 2) max = mid - 1;

else break;

}

long sum = 0;

for (int i = 1; i <= h; i++) sum += Math.min((mid - 1) / i, w);

sum--;

if (sum == (w * h) / 2) System.out.println(mid - 1);

else System.out.println(mid);

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值