题意:T个测试数据
下面给出n ,
从自然数( 从1开始 )中找到第 n 个不能开平方的数M 以及 M在图中公式求出的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
1 2 3 4 5 6 7 8 9 10 11 12 13 14
简单的说就是给出下面序列,求上面对应的数
方案一是比赛打的,后来发现做复杂了,不过按比赛时间来算,20分钟打个表比推公式可能好想点
方案一:预处理
思路:这里N最大是2^31 开平方后就是 46340 ,5位数还能接受,所以打表存在set里
首先求出M,可以把 每个平方数+1对应的n存到set中
也就是存入了
2 10 17
1 7 13
tnode[1]={2,1} ,tnode[2]={10,7}
可以得到 tnode[i]={ i^2 +1, i^2 - i } i^2 - i 就是i^2这个数减去其中所有的平方数
sum[i] 表示i^2 这个数在公式中求得的结果
mark:
#include<stdio.h>
#include<math.h>
#include<set>
using namespace std;
#define N 46340
#define ll __int64
struct node{
ll num,xu;//num表示xu对应的非平方数
bool operator < (const node & a) const{
return a.xu>xu;
}
}tnode;
set<node>ss;
set<node>::iterator p;
ll sum[N],num,temp,i;
int main(){
sum[0]=0; ss.clear();
for(i=1;i<N;i++)
{
sum[i]=(i*i-(i-1)*(i-1)-1)*(i-1)+sum[i-1]+i;//求和 M
tnode.num=i*i+1;
tnode.xu=tnode.num-i;
ss.insert(tnode);
}
int T;scanf("%d",&T);
while(T--){
scanf("%I64d",&num);
//temp是第一个答案,也就是“上面”的序列
tnode.xu=num;
p=ss.upper_bound(tnode);
if(p->xu==num)temp=tnode.num;
else
{
p--;
temp=num-p->xu+p->num;
}
ll sq=sqrt((double)temp);
printf("%I64d %I64d\n",temp,sum[sq]+(temp-sq*sq)*sq);
}
return 0;
}
方案二:
公式代入
(1+sqrt(1+4*a))/2;必需对这个数上取整,然后减一就是n了。
然后第a个非平方数就是 n*n+(a-n*n+n)=a+n
之后就是求另一个式子的值了,首先求1~n*n-1求和:
(2*n-1)*(n-1)对它从2到n求和得到:n*(n+1)*(2*n+1)/3-3*n*(n-1)/2+n;
之后加上 (n+a-n*n+1)*n;
#include<stdio.h>
#include<math.h>
int main()
{
int T;scanf("%d",&T);
__int64 n,a;
while(T--)
{
scanf("%I64d",&a);
n=ceil((1+sqrt((double)(1+4*a)))/2)-1;
printf("%I64d %I64d\n",n+a,n*(n+1)*(2*n+1)/3-3*(n+1)*n/2+n+(n+a-n*n+1)*n);
}
}