首页 > 代码库 > HDU2601,An easy problem

HDU2601,An easy problem

C - An easy problem
Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

When Teddy was a child , he was always thinking about some simple math problems ,such as “What it’s 1 cup of water plus 1 pile of dough ..” , “100 yuan buy 100 pig” .etc.. 

One day Teddy met a old man in his dream , in that dream the man whose name was“RuLai” gave Teddy a problem : 

Given an N , can you calculate how many ways to write N as i * j + i + j (0 < i <= j) ? 

Teddy found the answer when N was less than 10…but if N get bigger , he found it was too difficult for him to solve. 
Well , you clever ACMers ,could you help little Teddy to solve this problem and let him have a good dream ? 
 

Input

The first line contain a T(T <= 2000) . followed by T lines ,each line contain an integer N (0<=N <= 10 10).
 

Output

For each case, output the number of ways in one line.
 

Sample Input

2 1 3
 

Sample Output

0 1
 

该题确实在个简单的问题,因为可能形式很简单,但它又不是那么的简单。

如果这个题选择有两个for循环来写的话,那毫无疑问将超时,所以需要仔细分析一下,可以看出,N=i*j+i+j可以变形为:N+1=( i+1)*( j+1),且由 0<i<=j,可知:1<( i+1)<=( j+1),所以就以(i+1)为基准来进行循环,所以只需要单层循环即可。

再有,由于要考虑它的重复性,所以循环只需要进行到sqrt(N+1)即可,往后再循环的必重复。本题 i 要从1开始,所以 i+1 就要从2开始循环,一直到sqrt(N+1)(其实可以等于sqrt( N+1),此时 i=j,符合题意)。

当我想到这一步,我就感觉很明了了,易知(j+1)=( N+1)/(i+1),所以在循环里我用的判断是:if(((N+1)/(i+1))*( i+1)==n+1)

真不知道当时怎么短路了,会去这样判断,还是超时,后来到网上一看,才知道改成:if((N+1)%(i+1)==0)就行了,就解决了超时的问题。

耗时2562ms。

代码如下:


#include <stdio.h>
#include <string.h>
#include <math.h>
typedef __int64 int64;
int main()
{
	int64 i,j,n,count,t,k;
	scanf("%d",&t);
	while(t--)
	{
		count=0;
		scanf("%I64d",&n);
		k=sqrt(n+1);
		for(i=2;i<=k;i++)<span style="white-space:pre">		</span>//这里的i指的是i+1
			if((n+1)%i==0)
				count++;
		printf("%d\n",count);
	}
	return 0;
}

其实我还想到了能够进一步优化,先看:

①:奇 * 奇 + 奇 + 奇 = 奇

②:偶 * 偶 + 偶 + 偶 = 偶

③:奇 * 偶 + 奇 + 偶 = 奇

故可得,若 N 为偶数,那 i 和 j 也都是偶数,那 i+1就是从3开始,每次增加2,所以只需判断一下N是不是偶数就行了:

if(n%2==0)
		{
			for(i=3;i<=k;i+=2)
				if((n+1)%i==0)
					count++;
		}

那么全代码是:

#include <stdio.h>
#include <string.h>
#include <math.h>
typedef __int64 int64;
int main()
{
	int64 i,j,n,count,t,k;
	scanf("%d",&t);
	while(t--)
	{
		count=0;
		scanf("%I64d",&n);
		k=sqrt(n+1);
		if(n%2==0)
		{
			for(i=3;i<=k;i+=2)
				if((n+1)%i==0)
					count++;
		}
		else
		{
			for(i=2;i<=k;i++)
				if((n+1)%i==0)
					count++;
		}
		printf("%d\n",count);
	}
	return 0;
}

这样写,耗时会从上面的 2562ms 降到 1859ms,还行吧。