1. 程式人生 > >計算第K個能表示(2^i * 3^j * 5^k)的正整數(i,j,k為整數)?其前7個滿足此條件的數分別是1,2,3,4,5,6,8

計算第K個能表示(2^i * 3^j * 5^k)的正整數(i,j,k為整數)?其前7個滿足此條件的數分別是1,2,3,4,5,6,8

public class Main
{
    public static void main(String[] args)
    {
        int[] a = new int[1501];
        a[1] = 1;
        TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
        Deque<Integer> Q2 = new ArrayDeque<Integer>();
        Deque<Integer> Q3
= new ArrayDeque<Integer>(); Deque<Integer> Q5 = new ArrayDeque<Integer>(); map.put(2, 2); map.put(3, 3); map.put(5, 5); for (int i = 2; i < 1501; i++) { if (map.isEmpty()) break; Map.Entry<Integer
, Integer> e = map.pollFirstEntry(); int key = e.getKey(); int val = e.getValue(); if (val == 5) { Q5.add(key * 5); map.put(Q5.pollFirst(), 5); } else if (val == 3) { Q5.add(key * 5); Q3
.add(key * 3); map.put(Q3.pollFirst(), 3); } else { Q5.add(key * 5); Q3.add(key * 3); Q2.add(key * 2); map.put(Q2.pollFirst(), 2); } a[i] = key; } Scanner sc = new Scanner(System.in); while (sc.hasNext()) { System.out.println(a[sc.nextInt()]); } } }

算了前1500項,第K項存在a[K]裡
大概思路就是
(1)建三個佇列,Q2,Q3,Q5,存放的元素分別為2的倍數,3的倍數,5的倍數
(2)建一個容量為3的帶索引的小頂堆(這裡用map實現,key為值,value為標記來自哪個佇列)。並將2,3,5入堆,分別來自Q2,Q3,Q5
(3)加入元素並注意優化
取堆頂元素x,如果加入堆前其來自佇列Q2,則將2*x加入Q2,3*x加入Q3,5*X加入Q5。
如果加入堆前其來自佇列Q3,則將3*x加入Q3,5*x加入Q5
如果加入堆前其來自Q5,則將5*x加入Q5

證明:如果x來自Q3,則設x=3t。x能被加入堆,則t一定曾經出堆(t為1的時候不成立,但不影響)。由2*t<3*t=x,2*t一定在堆裡且已經出堆。由此,2*t*3已經加入堆,所以3*t*2(即2*x)無需再加入堆。Q5同理。

(4)令a[i]=x,i從2迴圈直至得到你需要的第K個