Sequence Sum Possibilities
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 5537   Accepted: 3641

Description

Most positive integers may be written as a sum of a sequence of at least two consecutive positive integers. For instance,

6 = 1 + 2 + 3
9 = 5 + 4 = 2 + 3 + 4
but 8 cannot be so written.

Write a program which will compute how many different ways an input number may be written as a sum of a sequence of at least two consecutive positive integers.

Input

The first line of input will contain the number of problem instances N on a line by itself, (1 ≤ N ≤ 1000) . This will be followed by N lines, one for each problem instance. Each problem line will have the problem number, a single space and the number to be written as a sequence of consecutive positive integers. The second number will be less than 231 (so will fit in a 32-bit integer).

Output

The output for each problem instance will be a single line containing the problem number, a single space and the number of ways the input number can be written as a sequence of consecutive positive integers.

Sample Input

7
1 6
2 9
3 8
4 1800
5 987654321
6 987654323
7 987654325

Sample Output

1 1
2 2
3 0
4 8
5 17
6 1
7 23
题目大意:输入一个整数n,问总共有多少个连续序列之和为这个数。

这道题目我推导出来了规律:

先把所有的等差为1的两数相加的和列出来,然后分别%2,发现结果均等于1

再把所有的等差为1的三个数相加和列出来,然后分别%3,发现结果均等于0

再把所有的等差为1的四个数相加和列出来,然后分别%4,发现结果均等于2

再把所有的等差为1的五个数相加和列出来,然后分别%5,发现结果均等于0

再把所有的等差为1的六个数相加和列出来,然后分别%6,发现结果均等于3

这就总结出来规律了,所有的偶数个等差为1的数列相加的和 除以 数列成员个数取余是得到一个递增的数。

所有的奇数个等差为1的数列相加的和 除以 数列成员个数取余是得到0,这就是得到最初的版本,

方法1:已经注掉的第一个for循环就是我的最初的版本,可以通过所有的用例。

但是会超时,因为当测试用例是987654321时候for循环要循环987654321/2次。

方法2:因为超时,所以要进行改进,发现从1开始 当等差为1的数列的和 与 输入的用例相等的时候,此时的数列长度会比用例直接除以2小很多(用例很大的情况下),所以改变一下for循环的判断条件会好很多。然后我就直接改掉了,但是测试的时候发现不对,调了一会发现原来是evenCal++写到内层if判断了,我又写到外层if判断就好了,

方法3:参考的别人的。假设首项为a1,长度为i,如果满足条件,则n = a1 * i + i * (i - 1) / 2;
即n -i * (i - 1) / 2 = a1 * i;也就是说n的值为长度为i,首项为a1的等差数列之和,所以只要判断(n -i * (i - 1) / 2) % i是否为0即可

/**
 * Copyright 2015 by ZhiShuo Zhang, Inc.,
 * 
 * POJ2853:
 * 
 * This programe I do not use any algorithm
 * I inducte by using below, and found the regular:
 * number can be written as a sum of a sequence of 2(3,4,5,6) consecutive positive integers
 * number%2 = 1
 * number%3 = 0
 * number%4 = 2
 * number%5 = 0
 * number%6 = 3
*/
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    int N;
    int i,j;
    int number,integer,evenCal;
    int Answer;
    cin>>N;
    for(i=1;i<=N;i++)
    {
        cin>>number;
        cin>>integer;
        Answer = 0;
        evenCal = 1;
        /*
        for(j=2;j<=(integer)/2;j++)    //1. this for conditional is too large.
        {
            if(j%2 == 0)
            {
                if(integer%j==evenCal)
                {
                    Answer++;
                    evenCal++;
                }
            }
            else
            {
                if(integer%j==0)
                {
                    Answer++;
                }
            }
        }
        */
        for(j=2;j<=sqrt(integer*2.0);j++) //2. only modify for conditional. for instances:
        {                                  //integer=1800, at most j=60.1+2+3...+60=1830>1800.
            if(j%2 == 0)                  //so this j will never bigger then 60. but for 1. why? 
            {
                if(integer%j==evenCal)
                {
                    Answer++;
                }
                evenCal++;
            }
            else
            {
                if(integer%j==0)
                {
                    Answer++;
                }
            }
        }
        /*
        for(j=2;j<=sqrt(integer*2.0);j++)    //3. this section is I refer other people, other methord.
        {                                    //n = a1 * i + i * (i - 1) / 2 ---> n -i * (i - 1) / 2 = a1 * i
            if ((integer - j * (j - 1) / 2) % j == 0)
            {
                Answer++;
            }
        }
        */
        cout<<number<<" "<<Answer<<endl;
    }
    return 0;
}

在这里有一个很奇怪的问题:

方法1能跑通所有的用例是因为什么呢?明明evenCal++写到内层if里面,这样的话就变成了只有偶数个长度的数列之和等于输入用例的时候,evenCal才自增,这没有按照一开始分析的规律来,肯定是不对的。可是偏偏这样却在满足第一种for循环的条件判断:integer/2下跑通所有的测试用例,目前还不理解为什么,以后有时间得好好分析分析。

posted on 2015-05-07 15:50  暴走路人甲  阅读(139)  评论(0)    收藏  举报