AC率:33.06% 时限:2000ms 内存限制:131072K
The numbers 1, 3, 6, 10, 15, 21, 28, 36, 45 and t_i=i(i+1)/2, are called half-consecutive.
For given N, find the smallest r which is no smaller than N such that t_r is square.
Input Format
The input contains multiple test cases.
The first line of a multiple input is an integer TT followed by TT input lines.
Each line contains an integer N(1≤N≤10^16).
Output Format
For each test case, output the case number first.
Then for given N, output the smallest r.
If this half-consecutive number does not exist, output −1.
样例输入
4
1
2
9
50
样例输出
Case #1: 1
Case #2: 8
Case #3: 49
Case #4: 288
题目来源
2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛
题意:
已知数列t_i=i*(i+1)/2,给出一个n。求一个i,i要大于等于n且保证t_i的值为平方数。
思路:
打表,我们首先知道有些连续的数答案是一样的,比如:
n=1,ans=1
n=2,ans=8
n=3,ans=8......
那么我们可以直接去找出这些ans,打表后可知这些数一共有22个。
打表技巧:
t_i为平方数的条件:
当i或(i+1)中,那个奇数它本身就是平方数,那个偶数要保证它本身除于2为平方数。例如8*9,9就是一个平方数;8=2*4,4也是一个平方数。
如果直接枚举i可能会很慢,那么我们直接枚举大于等于n的平方因子即可,我的代码是以奇数为基准,向i*i-1和i*i+1进行判断是否合法。
打表代码:
#include <bits/stdc++.h>
using namespace std;
long long x,y;
int judge(long long i,long long n)
{
if((long long)sqrt((i*i-1)/2)*(long long)sqrt((i*i-1)/2)==(i*i-1)/2&&i*i!=n) //i*i!=n是为了要保证x不能小于n
{
x=i*i-1;
y=i*i;
return 1;
}
else if((long long)sqrt((i*i+1)/2)*(long long)sqrt((i*i+1)/2)==(i*i+1)/2)
{
x=i*i;
y=i*i+1;
return 1;
}
else
{
return 0;
}
}
int main()
{
long long n=1,i;
while(n<=1e16)
{
i=(long long)ceil(sqrt(n)); //不能向下取整,要保证答案是大于等于n的
if(i%2==0) //我枚举的是奇数
{
i++;
}
while(judge(i,n)==0)
{
i=i+2;
}
printf("%lld\n",x);
n=y;
}
}
示例程序:
#include <bits/stdc++.h>
#define LDQ 1000000007
#define QAQ 0x3f3f3f3f
using namespace std;
long long a[22]={1,8,49,288,1681,9800,57121,332928,1940449,11309768,65918161,384199200,2239277041,13051463048,76069501249,443365544448,2584123765441,15061377048200,87784138523761,511643454094368,2982076586042449,17380816062160328};
int main()
{
int t,i,i1;
long long n;
scanf("%d",&t);
for(i=1;t>=i;i++)
{
scanf("%lld",&n);
for(i1=0;22>i1;i1++)
{
if(n<=a[i1])
{
break;
}
}
printf("Case #%d: %lld\n",i,a[i1]);
}
return 0;
}