【HDU 5312】Sequence(数学问题)

这个题看上去是一个贪心, 但是这个贪心显然是错的. 事实上这道题目很简单, 先判断1个是否可以, 然后判断2个是否可以. 之后找到最小的k (k > 2)k(k>2), 使得(m - k) mod 6 = 0(mk)mod6=0即可.

证明如下: 3n(n-1)+1 = 6(n*(n-1)/2)+13n(n1)+1=6(n(n1)/2)+1, 注意到n*(n-1)/2n(n1)/2是三角形数, 任意一个自然数最多只需要3个三角形数即可表示. 枚举需要kk个, 那么显然m=6(km=6(k个三角形数的和)+k)+k, 由于k \ge 3k3, 只要m-kmk是6的倍数就一定是有解的.

事实上, 打个表应该也能发现规律.


学了下三角形数的性质:

1.任意一个数都可以由三个三角形术表示

2.任何三角形数 * 8  + 1得到一个平方数

3.验证三角形数的公式:

n = (sqrt ( 8  *  X  +  1 ) - 1) / 2

如果为三角形数那么n为整数切为第n个

三角数具体连接:http://baike.baidu.com/view/1047488.htm

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 100000;
const int INF  = 1000000000;
int _list[maxn],cnt = 1,n;
void init(){
    while(1){
        _list[cnt] = 3 * cnt * (cnt - 1) + 1;
        if(_list[cnt] > INF) break;
        cnt ++;
    }
}
int Find(int value){
    return lower_bound(_list + 1,_list + cnt,value) - _list;
}
bool solve(int v){
    int l = 1,r = Find(v);
    while(l <= r){
        if(_list[l] + _list[r] > v)
            r --;
        else if(_list[l] + _list[r] < v)
            l ++;
        else
            return true;
    }
    return false;
}
bool can(int n){
    int d = (n - 1);
    if(d % 6 == 0){
        d /= 6;
        double dd = (sqrt(8.0 * d + 1.0) - 1.0) / 2;
        if(dd == (int)dd)
            return true;
    }
    return false;
}
int main(){
    init();
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        /*
            这里说一下,如果暴力找的话时间话费46ms
            如果利用判断是否为三角数的性质时间为31ms
        */
        /*if(_list[Find(n)] == n){
            printf("1\n");
        }*/
        if(can(n)){
            printf("1\n");
        }
        else{
            if((n - 2) % 6 == 0 && solve(n))
                printf("2\n");
            else{
                for(int i = 3; ; i++)
                    if((n - i) % 6 == 0){
                        printf("%d\n",i);
                        break;
                    }
            }
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值