So, that you can really understand WHAT A BAD STUDENT YOU ARE!!
4 1 3 6 10
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;
}