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

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


两边向中间找扫描的时候落了等号错了好多次,忘了数相等的时候也可以,最后找最小的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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值