读书人

在Java区看到一个比较有意思的题目转

发布时间: 2012-03-16 16:34:56 作者: rapoo

在Java区看到一个比较有意思的题目,转过来大家讨论一下
Consider all integer combinations of a^b for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5:

2^2=4, 2^3=8, 2^4=16, 2^5=32
3^2=9, 3^3=27, 3^4=81, 3^5=243
4^2=16, 4^3=64, 4^4=256, 4^5=1024
5^2=25, 5^3=125, 5^4=625, 5^5=3125

If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

How many distinct terms are in the sequence generated by a^b for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100?

翻译一下

就是有一个m*n的矩阵,

该矩阵的第一列是a^b,(a+1)^b,.....(a + n - 1)^b
第二列是a^(b+1),(a+1)^(b+1),.....(a + n - 1)^(b+1)
.......
第m列是(b + m - 1),(a+1)^(b + m - 1),.....(a + n - 1)^(b + m - 1)

问这个矩阵里有多少不重复的数
(比如4^3 = 8^2,这样的话就有重复了)

原题里面m和n的范围为100,这样的话就不用优化了,为了把问题搞难一些,让m和n都为10000吧。

[解决办法]
让我想想。。。

因数分解?


不好意思。。。我的程序非常烂的。

C# code
using System;using System.Collections.Generic;using System.Diagnostics;using System.Linq;using System.Text;namespace ConsoleApplication1{    class Program    {        class Node        {            public int Num { get; set; }            public Dictionary<int, int> Count { get; set; }            public Node() { Count = new Dictionary<int, int>(); }            public override string ToString()            {                string s = "";                foreach (var i in Count)                {                    s += "|" + Math.Pow((double)Num, (double)i.Key).ToString() + " " + i.Value.ToString();                }                return s;            }        }        static Dictionary<int, Node> Nodes = new Dictionary<int, Node>();        static List<int> Primers = new List<int>() { };        static void ProcPrimes(int num)        {            bool noprime = false;            foreach (var i in Primers)            {                if (num % i == 0)                {                    noprime = true;                    break;                }                else                {                    if (i > num) break;                }            }            if (!noprime) Primers.Add(num);        }        static void ToNodes(int num, int power)        {            List<int> list = new List<int>();            foreach (var i in Primers)            {                if (num % i == 0)                {                    list.Add(i);                    break;                }                else                {                    if (i > num) break;                }            }            int x = 1;            list.ForEach(x1 => x *= x1);            if (!Nodes.ContainsKey(x)) Nodes.Add(x, new Node(){ Num = x });            int pwr = num / x * power;            if (!Nodes[x].Count.ContainsKey(pwr))                 Nodes[x].Count.Add(pwr, 1);            else                Nodes[x].Count[pwr]++;        }        static int Solve(int startA, int endA, int startB, int endB)        {            Debug.Assert(startA > 1 && startB > 1);            Debug.Assert(endA > startA && endB > startB);            for (int i = 2; i <= endA; i++)                ProcPrimes(i);            for (int i = startA; i <= endA; i++)                for (int j = startB; j <= endB; j++)                    ToNodes(i, j);            Nodes.Values.ToList()                .ForEach(x => (from y                               in x.Count                               where y.Value > 0                               select Math.Pow((double)x.Num, (double)y.Key))                                .ToList().ForEach(z => Debug.WriteLine(z)));            int n = 0;            Nodes.ToList().ForEach(x => n += x.Value.Count.Count);            return n;                    }        static void Main(string[] args)        {            Console.WriteLine(Solve(2, 1000, 2, 1000));        }            }} 


[解决办法]

探讨

数组项为
x^y 令x=p^q (x ,y ,p ,q都是整数,且p为最小的满足条件的最小整数)
那么每一项都能表示为p^(y * q) 即p^z (z=y*q);
然后用这种形式来存放
只用比较 q , z就可以了
比较的方法有了,那就和100 * 100没什么区别了

[解决办法]
a^b, (a+1)^b, ..... (a + n - 1)^b
a^(b+1), (a+1)^(b+1), ..... (a + n - 1)^(b+1)
.......
a^(b + m - 1),(a+1)^(b + m - 1), ..... (a + n - 1)^(b + m - 1)

如果有两个数是相同的,那么它们一定不会在同一行,也不会在同一列
如果在同一行比如 i1行j1列 i2行j2列 (从0开始 )
那么(a + i1)^(b+j1) = (a+i2)^(b+j2)
显然 a+i1 和 a+i2可表示为 p^q1 ,p^q2
而且有 q1*(b+j1)=q2*(b+j2)

在查找的时候,可以只用查如下列
2^a1 - a, 2^(a1+1)-a ,... ,2^(a1+b1)-a ( 2^a1 - a >0 , 2^(a1+b1)-a<=10000)
3^a2 - a, 3^(a2+1)-a ,... ,3^(a2+b2)-a 同上
....
100^a99-a,...100^(a99+b99)-a 。。。

然后比较行数与(ai+bj)的积


[解决办法]
VB.NET code
  Dim m As Int64 = 5        Dim n As Int64 = 5        Dim value As New Hashtable        For a As Int64 = 2 To m            For b As Int64 = 2 To n                Dim c As String = Math.Pow(a, b)                Console.Write(a & "^" & b & "=" & c.ToString() & ",")                If IsNothing(value.Item(c)) Then                    value.Add(c, a.ToString() & "^" & b)                End If            Next            Console.WriteLine(" ")        Next        Console.WriteLine("数量:" & value.Count)        Console.ReadLine()
[解决办法]
99347607
C# code
using System;using System.Diagnostics;using System.Text;using System.Threading;using System.Collections.Generic;using System.Linq;class Program{    private const int N = 10000;    private static Dictionary<int, int> funResult;    private static HashSet<int> baseNumbers;    static void Main(string[] args)    {        InitFunResult();        InitBaseNumber();        int s = (int)Math.Sqrt((double)N);        int sum = 0, k = 0;        for (int i = 2; i <= N; i++)        {            if (baseNumbers.Contains(i)) continue;            if (i <= s)                k = (int)Math.Log((double)N, (double)i);            else                k = 1;                       sum += funResult[k];        }        Console.WriteLine(sum);        Console.Read();    }    private static void InitFunResult()    {        int maxK = (int)Math.Log((double)N, 2d);        funResult = new Dictionary<int, int>(maxK);        HashSet<int> set = new HashSet<int>();        int p;        for (int i = 1; i <= maxK; i++)        {            if (i == 1)                funResult[i] = 0;            else                funResult[i] = funResult[i - 1];            for (int j = 2; j <= N; j++)            {                p = i * j;                if (set.Add(i * j))                {                    funResult[i]++;                }            }        }           }    private static void InitBaseNumber()    {        baseNumbers = new HashSet<int>();        int s = (int)Math.Sqrt((double)N);        int p;        for (int i = 2; i <= s; i++)        {            for (int j = 2; j <= s; j++)            {                p = (int)Math.Pow((double)i, (double)j);                if (p <= N)                    baseNumbers.Add(p);                else                    break;            }                    }            }}using System;using System.Diagnostics;using System.Text;using System.Threading;using System.Collections.Generic;using System.Linq;class Program{    private const int N = 10000;    private static Dictionary<int, int> funResult;    private static HashSet<int> baseNumbers;    static void Main(string[] args)    {        InitFunResult();        InitBaseNumber();        int s = (int)Math.Sqrt((double)N);        int sum = 0, k = 0;        for (int i = 2; i <= N; i++)        {            if (baseNumbers.Contains(i)) continue;            if (i <= s)                k = (int)Math.Log((double)N, (double)i);            else                k = 1;                       sum += funResult[k];        }        Console.WriteLine(sum);        Console.Read();    }    private static void InitFunResult()    {        int maxK = (int)Math.Log((double)N, 2d);        funResult = new Dictionary<int, int>(maxK);        HashSet<int> set = new HashSet<int>();        int p;        for (int i = 1; i <= maxK; i++)        {            if (i == 1)                funResult[i] = 0;            else                funResult[i] = funResult[i - 1];            for (int j = 2; j <= N; j++)            {                p = i * j;                if (set.Add(i * j))                {                    funResult[i]++;                }            }        }           }    private static void InitBaseNumber()    {        baseNumbers = new HashSet<int>();        int s = (int)Math.Sqrt((double)N);        int p;        for (int i = 2; i <= s; i++)        {            for (int j = 2; j <= s; j++)            {                p = (int)Math.Pow((double)i, (double)j);                if (p <= N)                    baseNumbers.Add(p);                else                    break;            }                    }            }} 


[解决办法]
先假设N为100吧.

4 25 8 9 36这种底数不考虑 他等于2^2 5^5 2^3次方。

以2为底,指数的取值可以为:
(2 3 4 5 6 7 8 9 10 11 12 …… 100) 99个

(4 6 8 10 12 14 16 …… 200) 99 - 49 =50个
(49个是重复出现的比如 4 6 8就是以前出现过的)

(6,9,12,15,18,21,…… 300) 99 - N个重复
(6 12 18 …… 102 108 都是重复的,假设N个 )

因为100里面 2^6 = 64 所以 一共可以出现6此这样的情况
(2*6 3*6 4*6 5*6 …… 100*6) 也是 99-N个

然后3-100都是这样的计算。
[解决办法]

C# code
        static void Main()        {            int m = 10000, n = 10000;            filter3(m, n);            Console.ReadKey();        }        static void filter3(int m, int n)        {            List<PowerNum> list = PowerNumList(m);            list.Sort((x, y) =>            {                if (x.Base != y.Base)                {                    return x.Base - y.Base;                }                return y.Index - x.Index;            });            int count = 0;            list.ForEach((x) =>            {                for (int i = n; i >= 2; i--)                {                    int lowindex= x.Index- 1;                    while (lowindex > 0 && (x.Index * i) / lowindex <= n)                    {                        if ((x.Index * i) % lowindex == 0)                        {                            //Console.WriteLine("{0}^{1} ={2}^{3}", Math.Pow(x.Base,x.Index),i ,Math.Pow(x.Base,lowindex),i*x.Index/lowindex);                            count++;                            break;                        }                        lowindex--;                    }                }            });            Console.WriteLine("{0},{1}",count,(m-1)*(n-1)-count);        }        static List<PowerNum> PowerNumList(int max)        {            Dictionary<int, PowerNum> list = new Dictionary<int, PowerNum>();            for (int i = 2; i <= Math.Sqrt(max); i++)            {                int n = i, m = 1;                while ((n *= i) <= max)                {                    m++;                    if (!list.ContainsKey(n))                    {                        list[n] = new PowerNum() { Number = n, Base = i, Index = m };                    }                }            }            return list.Values.ToList();        }        class PowerNum        {            public int Number { get; set; }            public int Base { get; set; }            public int Index { get; set; }        }
[解决办法]
C# code
        static void Main()        {            int m =3 ,n =5,M = 10000, N = 10000;            filter3(m,n,M, N);            Console.ReadKey();        }        static void filter3(int s,int p, int m, int n)        {            List<PowerNum> list = PowerNumList(s, m);            int maxIndex = 0;            if(list.Count>0)maxIndex = list.Max((x) => {                return x.Index;            });            int[] indexCount = new int[maxIndex + 1];            for (int i = n; i >= p; i--)            {                for (int index = maxIndex ; index >= 2; index--)                {                    int lowindex = index - 1;                    while (lowindex > 0 && index * i <= n * lowindex)                    {                        if ((index * i) % lowindex == 0)                        {                            indexCount[index]++;                            break;                        }                        lowindex--;                    }                }            }            int count = 0;            list.ForEach((x) =>            {                count += indexCount[x.Index];            });            Console.WriteLine("{0},{1}",count,(m+1-s)*(n+1-p)-count);        }        static List<PowerNum> PowerNumList(int min, int max)        {            Dictionary<int, PowerNum> list = new Dictionary<int, PowerNum>();            int sqrt = (int)Math.Sqrt(max);            for (int i = min; i <= sqrt; i++)            {                int n = i, m = 1;                while ((n *= i) <= max)                {                    m++;                    if (!list.ContainsKey(n))                    {                        list[n] = new PowerNum() { Number = n, Base = i, Index = m };                    }                }            }            return list.Values.ToList();        }        class PowerNum        {            public int Number { get; set; }            public int Base { get; set; }            public int Index { get; set; }        } 

读书人网 >C#

热点推荐