题意: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); } }