hdu5331--Sequence(数学)

来源:互联网 发布:工程预算软件有哪些 编辑:程序博客网 时间:2024/06/05 11:26

题目链接:点击打开链接

这个题看上去是一个贪心, 但是这个贪心显然是错的. 事实上这道题目很简单, 先判断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的倍数就一定是有解的.

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

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


1 0
原创粉丝点击