2012 Multi-University Training Contest 5:History repeat itself

Problem Description
Tom took the Discrete Mathematics course in the 2011,but his bad attendance angered Professor Lee who is 
in charge of the course. Therefore, Professor Lee decided to let Tom face a hard probability problem, and ann
ounced that if he fail to slove the problem there would be no way for Tom to pass the final exam.
As a result , Tom passed.History repeat itself. You, the bad boy, also angered the Professor Lee when Septem
ber Ends. You have to faced the problem too.
The problem comes that You must find the N-th positive non-square number M and printed it. And that's for normal
 bad student, such as Tom. But the real bad student has to calculate the formula below.

So, that you can really understand WHAT A BAD STUDENT YOU ARE!!
 
Input
There is a number (T)in the first line , tell you the number of test cases below. For the next T lines, there is just 
one number on the each line which tell you the N of the case.
To simplified the problem , The N will be within 231 and more then 0.
 
Output
For each test case, print the N-th non square number and the result of the formula.
 
SampleInput
4
1
3
6
10
 
SampleOutput
2 2
5 7
8 13
13 28
 

//題意:給出一個n,求第n個非平方數m,並求出 1到m每個數的根號(取下界)之和。

//分析:1、假設不考慮是否爲平方數 ,直接詢問第n個數,那麼就是n, 而n前面有sqrt(n)個平方數,那麼再考慮平方數的情況下在 n前面就少計

算了sqrt(n)個數。  所以第n個平方數就是n+sqrt(n),但我們會發現 n到n+sqrt(n)之間可能也有平方數,那麼仍舊計算小了。  寫幾組數據其實就

可以發現,在計算sqrt(n)取整的時候需要取較近的那個整數點。 所以第n個非平方數爲n+[sqrt(n)];

2、找到m,則只需要計算1到m每個數的根號(取下界)之和。 從1一直到m每個數開根號會發現出現了3個1  ,  5個2  ,7個3  ,9個4,式子的

第二個數肯定是一直遞增1,而第一個數遞增2。那麼到m的時候肯定是(2*k-1)*sqrt(m)的形式。 所以只要循環到sqrt(m)利用這個規律則可以累加

值,需要注意的是最後的sqrt(m)不一定恰好就是(2*k-1)個。  則需先處理到sqrt(m)-1。 而另t=(int)sqrt(m)剩餘的便是(m-t*t+1)個sqrt(m)了。 時間

複雜度爲sqrt(n)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
#define LL __int64

int main()
{
	int t,i;
	scanf("%d",&t);
	while(t--)
	{
		LL n,m;
		scanf("%I64d",&n);
		double c=sqrt(1.0*n),tmp1=floor(c),tmp2=ceil(c);
		m=n+((c-tmp1)>(tmp2-c)?((int)tmp2):((int)tmp1));
	
		LL k=(int)sqrt(1.0*m);
		LL sum=0,cnt=3;
		for(i=1;i<=k-1;i++)
		{
			sum+=cnt*i;
			cnt+=2;
		}
		sum+=(m-k*k+1)*k;
		printf("%I64d %I64d\n",m,sum);
	}
	return 0;
}	


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章