HDU 4342 History repeat itself 2012 Multi-University Training Contest 5

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


 

你可能感兴趣的:(数论)