hdu5331--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的倍数就一定是有解的.

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

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值