| 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 + 3but 8 cannot be so written.
9 = 5 + 4 = 2 + 3 + 4
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下跑通所有的测试用例,目前还不理解为什么,以后有时间得好好分析分析。
浙公网安备 33010602011771号