To Add or to Multiply

From programming_contest
Revision as of 20:42, 25 August 2016 by imported>Kmk21 (Created page with "The number of multiplications is pretty small total. So assume some number of multiplications, then try inserting adds as early as possible in the multiplication stream in ord...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

The number of multiplications is pretty small total. So assume some number of multiplications, then try inserting adds as early as possible in the multiplication stream in order to stay below the target value. Iterate over all possible counts of multiplications to find the minimum.

Watch out for overflow.

import java.util.*;
public class a {
	Scanner in=new Scanner(System.in);
	long a,m,p,q,r,s;
	public static void main(String[] args) {
		new a().go();
	}
	private void go() {
		int cnum=0;
		while(true){
			cnum++;
			a=in.nextLong();
			m=in.nextLong();
			p=in.nextLong();
			q=in.nextLong();
			r=in.nextLong();
			s=in.nextLong();
			if(a==0&&m==0)break;
			if(p>=r&&p<=s&&q>=r&&q<=s){
				System.out.printf("Case %d: empty\n",cnum);
				continue;
			}
			long mult=0;
			ArrayList<long[]> l=new ArrayList<long[]>();//calculate best solution for any given number of multiplies
			while(true){//probably should be a for loop over # multiplies...whatever
				if((q-p)*Math.pow(m, mult)>(s-r)||mult>30)break;
				long[] test=new long[(int) (mult+1)];
				long lo=p;
				long hi=q;
				for(int i=0;i<test.length;i++){
					if(lo<0||hi<0)break;
					test[i]=Math.max(0,(long) ((r/Math.pow(m,test.length-i-1)-lo)/a));
					while((lo+a*test[i])*Math.pow(m, test.length-i-1)<r&&(hi+a*(test[i]+1))*Math.pow(m, test.length-i-1)<=s)test[i]++;
					lo+=a*test[i];
					lo*=m;
					hi+=a*test[i];
					hi*=m;
				}
				if(lo/m>=r&&hi/m<=s)l.add(test);
				mult++;
			}
			if(l.size()==0){
				System.out.printf("Case %d: impossible\n",cnum);
				continue;
			}
			long min=Long.MAX_VALUE;
			long[] ans={};
			for(long[] i:l){//choose shortest one...apparently this happens to work for lexicographical too....
				long count=i.length-1;
				for(long j:i)count+=j;
				if(count<min){
					min=count;
					ans=i;
				}
			}
			String out=String.format("Case %d: ",cnum);//printing is a bitch
			int mm=0;//number of multiplies built up
			for(int i=0;i<ans.length;i++){
				if(ans[i]!=0){//we have adds to add
					if(i!=0)out+=mm+"M ";//if we have multiplies built up, write them first
					out+=ans[i]+"A ";//write all the adds
					if(i<ans.length-1){//unless its the last add, we start over with 1 multiply
						mm=1;
					}else{
						mm=0;
					}
					continue;
				}
				if(i<ans.length-1)mm++;//or just add a multiply
			}
			if(mm!=0)out+=mm+"M ";//print the last multiplies if there are any
			System.out.println(out.substring(0,out.length()-1));//truncate the last space
		}
	}
}
//To Add or to Multiply
//math
//longs
//output
//overflow