2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 E.Half-consecutive Numbers

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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值