hdu 5312 Sequence

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5312

解题思路:

官方题解:

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

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

比赛的时候并没有发现这规律,只是将20000个数据打出来,然后再二分搜索,后来看了被别人hack的数据,才知道,有这回事。。。这怪当时太年轻,啥都不知道。。。也说明了自己打表时并没认真找规律。。。

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long ll;
ll a[20005];

void solve(ll n){
    if(n % 6 == 0){
        printf("6\n");
        return;
    }
    else if(n % 6 == 1){
        if(*lower_bound(a+1,a+20001,n) == n)
            printf("1\n");
        else
            printf("7\n");
        }
    else if(n % 6 == 2){
        int flag = 0;
        for(int i = 0, j = 20000; i <= 20000 && a[i] < n ; i++){
            while(j > 0 && a[i] + a[j] > n)
                j--;
            if(j > 0 && a[i] + a[j] == n){
                printf("2\n");
                flag = 1;
                break;
            }
        }
        if(!flag)
            printf("8\n");
        return;
    }
    else
        printf("%lld\n",n % 6);
}

int main(){
    for(ll i = 1; i <= 20000; i++){
        a[i] = 3 * i * (i-1) +1;
    }
    int T;
    scanf("%d",&T);
    while(T--){
        ll m;
        scanf("%lld",&m);
        solve(m);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值