疯狂地Jobdu序列

前言

打球打的太晚了,衣服还在洗衣机里,随便在九度oj上ac一题,当然难度不超过3星

题目

题目描述:
阳仔作为OJ的数据管理员,每一周的题目录入都让其很抓狂,因为题目不是他出的,他控制不了出题的速度……在等题目的时候,阳仔又不敢出去打篮球,所以只能在纸上乱涂乱写,这天,阳仔在纸上写下了这样的序列:
1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6 ……
即大小为k的数字,正好会在序列中连续重复k次。写到这里,阳仔兴奋了,但是他不知道这种序列叫什么名字,那就暂时叫它jobdu疯狂序列好了。现在阳仔想让你解决一个问题是,假如给你一个整数n,你能说出这个序列中,第n个元素的大小是多少么? 记住,速度要快哦,亲~
输入:
每个测试文件包含多个测试案例,每个测试案例只有一行,即整数n,1 <= n <= 10^18,代表要查找的第n个元素。
输出:
对于每个测试案例,输出疯狂的jobdu序列中的第n个元素。
样例输入:
1
2
3
4
5
样例输出:
1
2
2
3
3
提示:
输入较大,不建议使用cin读入输入数据。


思路

(1)看到这个题目,第一反应不就是个等差数列求和的题目,考虑每个数字1,2,3,4出现时n的数目,发现最后一个1,2,3,4都是满足等差数列的,大家可以自己推导一下,等差数列的求和公式:

这里a1为1,d为1,因此化简后si = (i * i + i) / 2,通过这里可以自然的写出一个可以解决问题的代码:

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    long long int i, n;
 
    while (scanf("%lld", &n) != EOF) {
        for (i = 0; (i * i + i) / 2 < n; i++) {
        }
        printf("%lld\n", i);
    }
 
    return 0;
}
/**************************************************************
    Problem: 1357
    User: wangzhengyi
    Language: C
    Result: Time Limit Exceed
****************************************************************/

大家可以看到,这种做法result里显示的是TLE,超时

(2)换个思路,既然知道了i * i + i = 2 * n,i是未知数,n是已知数,转换成了一元二次方程求解的问题了,一元二次方程的求解公式:


ok,看到这里我们就可以根据公式直接写出ac代码了

AC代码

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
int main()
{
    long long int i, n;
 
    while (scanf("%lld", &n) != EOF) {
        i = ceil((sqrt(1 + 8 * n) - 1) / 2);
        printf("%lld\n", i);
    }
 
    return 0;
}
 
/**************************************************************
    Problem: 1357
    User: wangzhengyi
    Language: C
    Result: Accepted
    Time:40 ms
    Memory:928 kb
****************************************************************/


posted @ 2013-05-03 17:32  java程序员填空  阅读(181)  评论(0编辑  收藏  举报