原题: http://poj.org/problem?id=3002
Description
Bill has found the perfect way to make money playing the slot machines. After months of careful research, he has finally figured out the mechanics behind how the machines operate. Now he is ready to make profit of his findings.
But first an introduction to the game. A slot machine consists of a number of wheels, usually three or four, each with a number of symbols printed on it – cherries, oranges, bells, etc. – and will show one of its symbols at a given time. To play, you insert a coin, push a button and the wheels start spinning. After spinning for a while, each wheel stops – at random it seems – at one of its symbols. If all wheels stop at the same symbol, or some nice combination of symbols, the player wins. One combination that is especially desirable is having the jackpot symbol on all wheels. This combination is simply called ’jackpot’ and will make you rich for life.
What Bill has discovered is that each wheel will stop at the jackpot symbol with a certain periodicity, which differs a lot between wheels. He has also figured out (after some sneeking around at the slot-machine factory) that all newly manufactured slot-machines are delivered showing the jackpot combination, and that they all have a counter at the back, telling how many times the machine has been played. This counter is always set to zero at delivery.
Now, all Bill needs to do is to calculate the number of times a machine has to be played between two occurrences of the jackpot combination. We will call this number the jackpot periodicity. This is of course the same as the number of times the machine has to be played after leaving the factory, before it gives its first jackpot. Thus, with a glance at the counter on the back of a machine, Bill can figure out if it is about to give a jackpot.
As Bill knows that you are a skillful computer programmer, he turns to you with the problem of calculating the jackpot periodicity. For each machine, he will give you the number of wheels, and the periodicity with which the jackpot symbol shows up on each wheel.
Input
One line with the number of machines n ≤ 20. For each machine, one line with the number of wheels w ≤ 5, and one line with w numbers, p1 , ..., pw the periodicity of each wheel pk ≤ 1000.
Output
One line per machine: The jackpot periodicity of the machine, if it is less than or equal to a billion (109 ), otherwise output the text ’More than a billion.’.
Sample Input
1
3
10 6 15
分析:问题实际上就是求n个整数的最小公倍数。解题思路参考笔者另外一篇博文“求k-1个数的最小公倍数”。
*****************
解法1: 质因素分解
import java.lang.reflect.Array; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Scanner; /** * * @author ljs * 2011-06-23 * */ public class Main { //factors is returned as factor-count pair,e.g. //n=2*2*2*2*3*5: returns [2,4,3,1,5,1] (factors are in asc. order) private static LinkedList<Integer> findFactors(int n){ LinkedList<Integer> factorList = new LinkedList<Integer>(); int p = n; for(int i=2;i<=p;i++){ int count = 0; while(n % i == 0){ count++; n /= i; } if(count>0){ factorList.add(i); factorList.add(count); } } return factorList; } private static Map<Integer,LinkedList<Integer>> factorAllNumbers(int[] nums){ Map<Integer,LinkedList<Integer>> factoredNumsMap =new HashMap<Integer,LinkedList<Integer>>(); for(int i=0;i<nums.length;i++){ //no need to calculate the factors for duplicate numbers if(factoredNumsMap.get(nums[i]) == null){ LinkedList<Integer> currFactors = Main.findFactors(nums[i]); factoredNumsMap.put(nums[i],currFactors); } } return factoredNumsMap; } private static LinkedList<Integer> findTwoNumbersLCM(LinkedList<Integer> prev,LinkedList<Integer> next){ int j=next.size()-1; //next list's position LinkedList<Integer> curr = new LinkedList<Integer>(prev); if(curr.size()==0){ curr.addAll(next); } for(int i=curr.size()-1;i>=0;i-=2){ int count = curr.get(i); int factor = curr.get(i-1); while(j>=0){ int jcount = next.get(j); int jfactor = next.get(j-1); if(jfactor == factor){ if(jcount>count){ //update the factor's count curr.set(i, jcount); } j-=2; break; }else { if(jfactor > factor){ //insert int insertAt = i + 1; if(insertAt<curr.size()){ curr.add(insertAt,jcount); curr.add(insertAt,jfactor); }else{ curr.addLast(jfactor); curr.addLast(jcount); } j-=2; //don't move i; }else { //add as a first element if(i-1==0){ curr.addFirst(jcount); curr.addFirst(jfactor); j-=2; //i has moved to head position }else{ //don't move j break; } } } } } //insert the least factors at the front while(j>=0){ int jcount = next.get(j); int jfactor = next.get(j-1); curr.addFirst(jcount); curr.addFirst(jfactor); j-=2; } return curr; } private static long findLCM(LinkedList<Integer>[] factorsList){ LinkedList<Integer> currFactors = factorsList[0]; for(int i=1;i<factorsList.length;i++){ LinkedList<Integer> nextFactors = factorsList[i]; currFactors = Main.findTwoNumbersLCM(currFactors, nextFactors); } //caculate the lcm value long lcm = 1; for(int i=0;i<currFactors.size();i+=2){ int factor = currFactors.get(i); int count = currFactors.get(i+1); lcm *= (int)Math.pow(factor, count); } return lcm; } //find the minimum lcm among k-1 numbers (k=nums.length) @SuppressWarnings("unchecked") public static long solve(int[] nums){ Map<Integer,LinkedList<Integer>> factoredNumsMap =Main.factorAllNumbers(nums); int k =nums.length; LinkedList<Integer>[] factorsArr = (LinkedList<Integer>[])Array.newInstance(LinkedList.class,k); for(int j=0;j<k;j++){ factorsArr[j] = factoredNumsMap.get(nums[j]); } long lcm = Main.findLCM(factorsArr); return lcm; } public static void main(String[] args) { Scanner cin = new Scanner(System.in); String line = cin.nextLine(); line = line.trim(); int machinesCount = Integer.parseInt(line); int[][] testCases = new int[machinesCount][]; for (int i = 0; i < machinesCount; i++) { line = cin.nextLine(); line = line.trim(); int w = Integer.parseInt(line); line = cin.nextLine(); line = line.trim(); int[] p = new int[w]; String[] tokens = line.split(" "); for (int j = 0; j < tokens.length; j++) { String token = tokens[j].trim(); if (token.length() > 0 && j < w) { p[j] = Integer.parseInt(token); } } testCases[i] = p; } for (int i = 0; i < machinesCount; i++) { int[] p = testCases[i]; long result = Main.solve(p); if(result<=1000000000){ System.out.println(result); }else{ System.out.println("More than a billion."); } } } }
*****************
解法2: 通过gcd求lcm
import java.lang.reflect.Array; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Scanner; /** * * @author ljs * 2011-06-23 * */ public class Main { public static long gcd(long m,long n){ m = (m<0)?-m:m; n = (n<0)?-n:n; while(n!=0){ long remainder = m%n; m = n; n = remainder; } return m; } public static long solve(int[] nums){ int k = nums.length; long lcm = 1; for(int j=0;j<k;j++){ if(nums[j]<lcm){ lcm = lcm/gcd(lcm,nums[j])*nums[j]; }else{ lcm = nums[j]/gcd(lcm,nums[j])*lcm; } } return lcm; } public static void main(String[] args) { Scanner cin = new Scanner(System.in); String line = cin.nextLine(); line = line.trim(); int machinesCount = Integer.parseInt(line); int[][] testCases = new int[machinesCount][]; for (int i = 0; i < machinesCount; i++) { line = cin.nextLine(); line = line.trim(); int w = Integer.parseInt(line); line = cin.nextLine(); line = line.trim(); int[] p = new int[w]; String[] tokens = line.split(" "); for (int j = 0; j < tokens.length; j++) { String token = tokens[j].trim(); if (token.length() > 0 && j < w) { p[j] = Integer.parseInt(token); } } testCases[i] = p; } for (int i = 0; i < machinesCount; i++) { int[] p = testCases[i]; long result = Main.solve(p); if(result<=1000000000){ System.out.println(result); }else{ System.out.println("More than a billion."); } } } }
以上两个都是AC解。
类似的一道求LCM题:http://acm.hdu.edu.cn/showproblem.php?pid=1019
该题只能用gcd的方法,才能AC(poj的题因为限制w ≤ 5所以质因数分解耗时不会太多):
import java.util.Scanner; /** * * @author ljs * 2011-06-23 * */ public class Main { public static long gcd(long m,long n){ m = (m<0)?-m:m; n = (n<0)?-n:n; while(n!=0){ long remainder = m%n; m = n; n = remainder; } return m; } public static long solve(int[] nums){ int k = nums.length; long lcm = 1; for(int j=0;j<k;j++){ if(nums[j]<lcm){ lcm = lcm/gcd(lcm,nums[j])*nums[j]; }else{ lcm = nums[j]/gcd(lcm,nums[j])*lcm; } } return lcm; } public static void main(String[] args) { Scanner cin = new Scanner(System.in); String line = cin.nextLine(); line = line.trim(); int testCasesNum = Integer.parseInt(line); int[][] testCases = new int[testCasesNum][]; for (int i = 0; i < testCasesNum; i++) { line = cin.nextLine(); line = line.trim(); int[] p = null; String[] tokens = line.split(" "); for (int j = 0,m=0; j < tokens.length; j++) { String token = tokens[j].trim(); if (j==0) { p = new int[Integer.parseInt(token)]; }else{ if (token.length() > 0 && m < p.length) { p[m++] = Integer.parseInt(token); } } } testCases[i] = p; } for (int i = 0; i < testCasesNum; i++) { int[] p = testCases[i]; long result = Main.solve(p); System.out.println(result); } } }