計算第K個能表示(2^i * 3^j * 5^k)的正整數(i,j,k為整數)?其前7個滿足此條件的數分別是1,2,3,4,5,6,8
阿新 • • 發佈:2019-01-25
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個