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

HDU--5312(规律+数学)

时间:2015-08-13 22:20:19      阅读:101      评论: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,直接取余就行,最少是从3开始的。

#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define INF 9999999999
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef unsigned long long llu;
typedef long long ll;
const int maxd=18258+5;
///=========================
int s[maxd];
int m;
void table()
{
    s[0]=0;
    for(int i=1;i<maxd;i++)
        s[i]=3*i*(i-1)+1;
}

bool ok1(int x)
{
    int pos=lower_bound(s,s+maxd,x)-s;
    if(s[pos]==x) return true;
    return false;
}

bool ok2(int x)
{
    if((x-2)%6) return false;
    int l=1,r=maxd-1;
    while(l<=r)
    {
        if(s[l]+s[r]<x)
            l++;
        else if(s[l]+s[r]>x)
            r--;
        else return true;
    }
    return false;
}

int main()
{
    int kase;
    // freopen("1.txt","r",stdin);
    table();
    scanf("%d",&kase);
    while(kase--)
    {
        scanf("%d",&m);
        if(ok1(m))
            printf("1\n");
        else if(ok2(m))
            printf("2\n");
        else
        {
//            for(int k=3;k<=m;k++)
//                if((m-k)%6==0)
//            {
//                printf("%d\n",k);
//                break;
//            }
           printf("%d\n",(m-3)%6+3);
        }
    }
    return 0;
}


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

HDU--5312(规律+数学)

标签:

原文地址:http://blog.csdn.net/whoisvip/article/details/47126707

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