原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2058
思路:等差数列公式变形:sum = a1 * len + len *(len -1)/2
抽象成一句话就是本题的思路:根据数列的长度和数列的和就可以算出首项,因为知道长度,所以区间就出来了(看了好多博客,都没说清楚,晕我一大天……)
然后由式子的变形(2*a1 + len -1)*len = 2 *sum可得len绝对小于Sqrt(2*sum),因为a1>=1故len-1+2*a1>len(模糊比较即可)
下面判断就用一个双重确定就可以了,因为double转long会丢失精度,所以如果转换之后依然相等,就说明找到了,输出即可
source code:
package hduoj; import java.util.Scanner; public class hdoj_2058 { /** * 注释掉的是穷举法,超时了 * 需要使用的是等差数列的公式sum = 2 * len +len(len-1)/2 */ // public static void main(String[] args) { // Scanner sc = new Scanner(System.in); // while(true){ // long N = sc.nextLong(); // long M = sc.nextLong(); // if(N==0||M==0) break; // HashMap<Long,Long> map = new HashMap<>(); // long start = 0; //// long end = 0; // for(long i = 1;i<M/2;++i){ // long sum = i; // start = i; // long j ; // for(j = i+1;j<Math.sqrt(M);++j){ // sum += j; // if(sum==M){ // map.put(start,j); // } // if(sum>M) break; // } // } // if(map.size()==0) System.out.println("["+M+","+M+"]"); // else { // map.put(M,M); // for(Map.Entry<Long,Long> each : map.entrySet()){ // System.out.println("["+each.getKey()+","+each.getValue()+"]"); // } // } // } // } public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(true){ long N = sc.nextLong(); long M = sc.nextLong(); if(N==0||M==0) break; long len = (long)Math.sqrt(2*M) + 1;//此处加一是因为下面的循环判断条件会减一个一,如果不加就会少一个长度 while(len--!=1){ long start = (2*M/len + 1 - len)/2; if((2*start + len -1)*len/2 == M){ System.out.println("["+start+","+(start + len -1)+"]"); } } System.out.println(); } } }
代码已经ac
希望对大家有所帮助
以上