我的有道难题算法-双倍超立方数
题目要求:双倍超立方数是指一个正整数可以正好被拆分为两种不同的a^3+b^3的方式,其中a,b均为整数且0a=b。对于任何一个指定的 int n, 返回所有的小于等于n的双倍超立方数的个数。
因为题中大量使用3次方计算,这里我们也可以减少重复计算。原理公式为:
(n + 1)^2 = n^2 + 2n + 2
(n + 1)^3 = n^3 + 3n^2 + 3n + 1
题目要求:双倍超立方数是指一个正整数可以正好被拆分为两种不同的a^3+b^3的方式,其中a,b均为整数且0<a<=b。对于任何一个指定的 int n, 返回所有的小于等于n的双倍超立方数的个数。
Definition
Class: TwiceSuperCubic
Method: count
Parameters: int
Returns: int
Method signature: int count(int n)
(be sure your method is public)
Constraints
- n取值范围为1到1,000,000,000(含)
Examples
0)
1
Returns: 0
1)
1729
Returns: 1
1729=1^3+12^3
1729=9^3+10^3
2)
475574
Returns: 27
因为题中大量使用3次方计算,这里我们也可以减少重复计算。原理公式为:
(n + 1)^2 = n^2 + 2n + 2
(n + 1)^3 = n^3 + 3n^2 + 3n + 1
所以我的实现算法如下:
Code
class Program
{
static void Main(string[] args)
{
TwiceSuperCubic twice = new TwiceSuperCubic();
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
Dictionary<int, List<int[]>> ret = null;
watch.Start();
for (int i = 0; i < 1000; i++)
{
twice.CalcCount(475574, out ret);
}
watch.Stop();
Console.WriteLine("======================");
foreach (KeyValuePair<int, List<int[]>> pair in ret)
{
if (pair.Value.Count == 2)
{
foreach (int[] val in pair.Value)
{
Console.WriteLine("{0}^3 + {1}^3 = {2}", val[0], val[1], pair.Key);
}
}
}
Console.WriteLine("======================");
Console.WriteLine(twice.CalcCount(1729));
Console.WriteLine(twice.CalcCount(475574));
Console.WriteLine("用时:{0}毫秒", watch.ElapsedMilliseconds);
Console.WriteLine("======================");
Console.WriteLine(T2.count(1729));
Console.WriteLine(T2.count(475574));
watch.Start();
for (int i = 0; i < 1000; i++)
{
T2.count(475574);
}
watch.Stop();
Console.WriteLine("用时:{0}毫秒", watch.ElapsedMilliseconds);
Console.ReadKey();
}
}
/// <summary>
/// evlon算法
/// </summary>
public class TwiceSuperCubic
{
private static List<int> pow2 = new List<int>(new int[]{0});
private static List<int> pow3 = new List<int>(new int[]{0});
public int CalcCount(int n)
{
Dictionary<int, List<int[]>> debugInfo;
return CalcCount(n, out debugInfo);
}
public int CalcCount(int n, out Dictionary<int, List<int[]>> debugInfo)
{
debugInfo = new Dictionary<int, List<int[]>>();
int maxi = Convert.ToInt32(Math.Pow(n, 1.0 / 3)) + 1;
for(int i = pow2.Count; i < maxi; ++i)
{
int pos = i - 1;
pow2.Add(pow2[pos] + (pos << 1) + 1); // (n + 1)^2 = n^2 + 2n + 2
pow3.Add(pow3[pos] + (pow2[pos] << 1) + pow2[pos] + (pos << 1) + pos + 1); // (n + 1)^3 = n^3 + 3n^2 + 3n + 1
}
int count = 0;
for(int x = 1; x < maxi; ++x)
{
bool found = false;
for(int y = x; y < maxi; ++y)
{
int z = pow3[x] + pow3[y];
if( z <= n)
{
if (!debugInfo.ContainsKey(z))
{
debugInfo.Add(z, new List<int[]>(new int[][] { new int[] { x, y } }));
found = true;
}
else
{
List<int[]> val = debugInfo[z];
val.Add(new int[] { x, y });
if (val.Count == 2)
count++;
else
count--;
}
}
else
{
break;
}
}
if(!found)
break;
}
return count;
}
}
/// <summary>
/// ealget的算法
/// </summary>
class T2
{
static List<int> _CubeCache = new List<int>();
static Dictionary<int, int> _CubeCountDict = new Dictionary<int, int>();
/**/
/// <summary>
///
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
/// <author>eaglet</author>
static public int count(int n)
{
if (n < 0)
{
return 0;
}
_CubeCountDict.Clear();
//b <= n 的 3 次方根
int max_b = (int)Math.Pow((double)n, 1f / 3);
//构造整数三次方计算缓存
for (int i = _CubeCache.Count; i <= max_b; i++)
{
_CubeCache.Add(i * i * i);
}
int count = 0;
int a = 1; //正整数
int b = a;
int sumCube;
sumCube = _CubeCache[a] + _CubeCache[b];
do
{
//计算 a^3+b^3
while (sumCube <= n)
{
int hit;
//看hash表中有没有已经存在的记录
if (_CubeCountDict.TryGetValue(sumCube, out hit))
{
//存在,且只击中了1次,则计数加1
if (hit == 1)
{
count++;
}
//击中超过1次,计数减1
//存在三组或以上组合相等的情况时走到这个分支
if (hit == 2)
{
count--;
}
//击中数加一
_CubeCountDict[sumCube]++;
}
else
{
_CubeCountDict.Add(sumCube, 1);
}
b++;
if (b > max_b)
{
break;
}
sumCube = _CubeCache[a] + _CubeCache[b];
}
a++;
b = a;
if (b > max_b)
{
break;
}
sumCube = _CubeCache[a] + _CubeCache[b];
}
while (sumCube <= n);
return count;
}
}
class Program
{
static void Main(string[] args)
{
TwiceSuperCubic twice = new TwiceSuperCubic();
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
Dictionary<int, List<int[]>> ret = null;
watch.Start();
for (int i = 0; i < 1000; i++)
{
twice.CalcCount(475574, out ret);
}
watch.Stop();
Console.WriteLine("======================");
foreach (KeyValuePair<int, List<int[]>> pair in ret)
{
if (pair.Value.Count == 2)
{
foreach (int[] val in pair.Value)
{
Console.WriteLine("{0}^3 + {1}^3 = {2}", val[0], val[1], pair.Key);
}
}
}
Console.WriteLine("======================");
Console.WriteLine(twice.CalcCount(1729));
Console.WriteLine(twice.CalcCount(475574));
Console.WriteLine("用时:{0}毫秒", watch.ElapsedMilliseconds);
Console.WriteLine("======================");
Console.WriteLine(T2.count(1729));
Console.WriteLine(T2.count(475574));
watch.Start();
for (int i = 0; i < 1000; i++)
{
T2.count(475574);
}
watch.Stop();
Console.WriteLine("用时:{0}毫秒", watch.ElapsedMilliseconds);
Console.ReadKey();
}
}
/// <summary>
/// evlon算法
/// </summary>
public class TwiceSuperCubic
{
private static List<int> pow2 = new List<int>(new int[]{0});
private static List<int> pow3 = new List<int>(new int[]{0});
public int CalcCount(int n)
{
Dictionary<int, List<int[]>> debugInfo;
return CalcCount(n, out debugInfo);
}
public int CalcCount(int n, out Dictionary<int, List<int[]>> debugInfo)
{
debugInfo = new Dictionary<int, List<int[]>>();
int maxi = Convert.ToInt32(Math.Pow(n, 1.0 / 3)) + 1;
for(int i = pow2.Count; i < maxi; ++i)
{
int pos = i - 1;
pow2.Add(pow2[pos] + (pos << 1) + 1); // (n + 1)^2 = n^2 + 2n + 2
pow3.Add(pow3[pos] + (pow2[pos] << 1) + pow2[pos] + (pos << 1) + pos + 1); // (n + 1)^3 = n^3 + 3n^2 + 3n + 1
}
int count = 0;
for(int x = 1; x < maxi; ++x)
{
bool found = false;
for(int y = x; y < maxi; ++y)
{
int z = pow3[x] + pow3[y];
if( z <= n)
{
if (!debugInfo.ContainsKey(z))
{
debugInfo.Add(z, new List<int[]>(new int[][] { new int[] { x, y } }));
found = true;
}
else
{
List<int[]> val = debugInfo[z];
val.Add(new int[] { x, y });
if (val.Count == 2)
count++;
else
count--;
}
}
else
{
break;
}
}
if(!found)
break;
}
return count;
}
}
/// <summary>
/// ealget的算法
/// </summary>
class T2
{
static List<int> _CubeCache = new List<int>();
static Dictionary<int, int> _CubeCountDict = new Dictionary<int, int>();
/**/
/// <summary>
///
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
/// <author>eaglet</author>
static public int count(int n)
{
if (n < 0)
{
return 0;
}
_CubeCountDict.Clear();
//b <= n 的 3 次方根
int max_b = (int)Math.Pow((double)n, 1f / 3);
//构造整数三次方计算缓存
for (int i = _CubeCache.Count; i <= max_b; i++)
{
_CubeCache.Add(i * i * i);
}
int count = 0;
int a = 1; //正整数
int b = a;
int sumCube;
sumCube = _CubeCache[a] + _CubeCache[b];
do
{
//计算 a^3+b^3
while (sumCube <= n)
{
int hit;
//看hash表中有没有已经存在的记录
if (_CubeCountDict.TryGetValue(sumCube, out hit))
{
//存在,且只击中了1次,则计数加1
if (hit == 1)
{
count++;
}
//击中超过1次,计数减1
//存在三组或以上组合相等的情况时走到这个分支
if (hit == 2)
{
count--;
}
//击中数加一
_CubeCountDict[sumCube]++;
}
else
{
_CubeCountDict.Add(sumCube, 1);
}
b++;
if (b > max_b)
{
break;
}
sumCube = _CubeCache[a] + _CubeCache[b];
}
a++;
b = a;
if (b > max_b)
{
break;
}
sumCube = _CubeCache[a] + _CubeCache[b];
}
while (sumCube <= n);
return count;
}
}
QQ:273352165
evlon#126.com
转载请注明出处。