码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5331--Sequence(数学)

时间:2015-07-27 16:18:03      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:点击打开链接

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

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

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

求k==1时用二分找出结果

求k==2时,对于一个有序的数组,求两个值的和是不是n,用两个指针,一个指向头,一个指向为,不断向另一个方向逼近,就可以找到是否存在和为n


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int a[21000] ;
void init() {
    for(int i = 1 ; i <= 20000 ; i++) {
        a[i] = 3*i*(i-1)+1 ;
    }
}
int binSearch(int x,int high){
    int low = 1 , mid , k ;
    while( low <= high ) {
        mid = (low+high)/2 ;
        if( a[mid] <= x ) {
            k = mid ;
            low = mid + 1 ;
        }
        else
            high = mid - 1 ;
    }
    return k ;
}
int main() {
    int t , m , n , k , i , j , l , r ;
    init() ;
    scanf("%d", &t) ;
    while( t-- ) {
        scanf("%d", &m) ;
        n = binSearch(m,20000) ;
        if( a[n] == m ) {
            printf("1\n") ;
            continue ;
        }
        l = 1 ; r = n ;
        while( l <= r ) {
            if( a[l]+a[r] == m ) break ;
            if( a[l]+a[r] < m ) l++ ;
            else r-- ;
        }
        if( l <= r ) {
            printf("2\n") ;
            continue ;
        }
        k = 3 ;
        while( 1 ) {
            if( (m-k)%6 == 0 ) break ;
            else k++ ;
        }
        printf("%d\n", k) ;
    }
    return 0 ;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu5331--Sequence(数学)

标签:

原文地址:http://blog.csdn.net/winddreams/article/details/47086135

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!