hdu 5312 Sequence

来源:互联网 发布:windows无法识别音响 编辑:程序博客网 时间:2024/06/09 11:24

题目链接:

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


0 0
原创粉丝点击