2

非常に大きな仮想グリッド内で関心のある特定の座標を見つけようとしています。寸法が大きいため、このグリッドは実際にはメモリに存在しません。この質問のために、それらの次元をであると仮定しましょう(Width x Height) = (Int32.MaxValue x Int32.MaxValue)

  1   2   3   4   5   6   7   8   9  10
  2   4   6   8  10  12  14  16  18  20
  3   6   9  12  15  18  21  24  27  30
  4   8  12  16  20  24  28  32  36  40
  5  10  15  20  25  30  35  40  45  50
  6  12  18  24  30  36  42  48  54  60
  7  14  21  28  35  42  49  56  63  70
  8  16  24  32  40  48  56  64  72  80
  9  18  27  36  45  54  63  72  81  90
 10  20  30  40  50  60  70  80  90 100

グリッドに関する既知のデータ:

  • グリッドの寸法= (Int32.MaxValue x Int32.MaxValue)
  • 任意(x, y)の座標での値=XとYの積= (x * y)

(x * y)上記の有限数の大きなセットを考えると、値がの累乗である座標のセットを計算する必要がありますeeこの場合は2だとしましょう。

グリッドをループすることはオプションではないので、私はループすることを考えました:

int n = 0;
long r = 0;
List<long> powers = new List<long>();
while (r < (Int32.MaxValue * Int32.MaxValue))
{
    r = Math.Pow(e, n++);
    powers.Add(r);
}

これは私たちにユニークな力のセットを与えます。ここで、各パワーがどの座標に存在するかを調べる必要があります。取りましょう2^3=8。上のグリッドに示されているように、8つは4つの座標に存在します(8,1), (4,2), (2,4) & (1, 8)

明らかに、ここでの問題は、数値8の複数の因子を見つけることですが、これは、数値が大きい場合には実用的ではなくなります。これを達成する別の方法はありますか?私は何かを逃していますか?

  • 因子がメモリに存在しないため、セットの使用は機能しません。
  • 問題の数が常にの累乗になることを知って因数分解する創造的な方法はありeますか?
4

2 に答える 2

2

最良の方法は、eをプライムコンポーネントに因数分解することです。それらが次のようであるとしましょう:{a ^ m、b ^ p、c^q}。次に、eの累乗ごとにセットを作成します。たとえば、m = 2、p = 1、q = 3の場合、

e ^ 1 = {a、a、b、c、c、c}

e ^ 2 =(a、a、a、a、b、b、c、c、c、c、c、c}

などe^Kまで>Int32.MaxValue* Int32.MaxValue

次に、セットごとに、これらのセットの一意のサブセットを繰り返し処理して、1つの座標を形成する必要があります。他の座標は残っているものです。eの一意の素数ごとに1つのネストされたループが必要になります。例えば:

e^2としましょう

  M=m*m;
  P=p*p;
  Q=q*q;

  c1 = 1 ;
  for (i=0 ; i<=M ; i++)
  {
    t1 = c1 ;
    for (j=0 ; j<=P ; j++)
    {
      t2 = c1 ;
      for (k=0 ; k<=Q ; k++)
      {
        // c1 holds first coordinate
        c2 = e*e/c1 ;
        // store c1, c2

        c1 *= c ;
      }
      c1 = t2*b ;
    }
    c1 = t1*a ;
  }

(M + 1)(P + 1)(Q + 1)個の一意の座標が必要です。

于 2012-07-28T13:24:18.623 に答える
1

Commodore63のアイデアほど洗練されていないが、おそらく少し単純な別の解決策(素因数分解を実行し、すべての適切なサブセットを計算する必要はありません):

const int MaxX = 50;
const int MaxY = 50;
const int b = 6;

var maxExponent = (int)Math.Log((long)MaxX * MaxY, b);

var result = new List<Tuple<int, int>>[maxExponent + 1];
for (var i = 0; i < result.Length; ++i)
  result[i] = new List<Tuple<int, int>>();

// Add the trivial case
result[0].Add(Tuple.Create(1, 1));

// Add all (x,y) with x*y = b
for (var factor = 1; factor <= (int)Math.Sqrt(b); ++factor)
  if (b % factor == 0)
    result[1].Add(Tuple.Create(factor, b / factor));

// Now handle the rest, meaning x > b, y <= x, x != 1, y != 1
for (var x = b; x <= MaxX; ++x) {
  if (x % b != 0)
    continue;

  // Get the max exponent for b in x and the remaining factor
  int exp = 1;
  int lastFactor = x / b;
  while (lastFactor >= b && lastFactor % b == 0) {
    ++exp;
    lastFactor = lastFactor / b;
  }

  if (lastFactor > 1) {
    // Find 1 < y < b with x*y yielding a power of b
    for (var y = 2; y < b; ++y)
      if (lastFactor * y == b)
        result[exp + 1].Add(Tuple.Create(x, y));
  } else {
    // lastFactor == 1 meaning that x is a power of b
    // that means that y has to be a power of b (with y <= x)
    for (var k = 1; k <= exp; ++k)
      result[exp + k].Add(Tuple.Create(x, (int)Math.Pow(b, k)));
  }
}

// Output the result
for (var i = 0; i < result.Length; ++i) {
  Console.WriteLine("Exponent {0} - Power {1}:", i, Math.Pow(b, i));
  foreach (var pair in result[i]) {
    Console.WriteLine("  {0}", pair);
    //if (pair.Item1 != pair.Item2)
    //  Console.WriteLine("  ({0}, {1})", pair.Item2, pair.Item1);
  }
}
于 2012-07-28T14:52:27.807 に答える