HDU5312.Sequence

来源:互联网 发布:沈阳seo技术 编辑:程序博客网 时间:2024/06/06 00:50

这个题看上去是一个贪心, 但是这个贪心显然是错的. 事实上这道题目很简单, 先判断1个是否可以, 然后判断2个是否可以. 之后找到最小的k (k > 2)(k>2), 使得(m - k) mod 6 = 0即可.

证明如下: 3n(n-1)+1 = 6(n*(n-1)/2),注意到n*(n-1)/2是三角形数, 任意一个自然数最多只需要3个三角形数即可表示(高斯发现). 枚举需要k个, 那么显然m=6*(k个三角形数和)+k, 由于k≥3, 只要m-k是6的倍数就一定是有解的.
事实上, 打个表应该也能发现规律.

#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <ctime>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;#define INF 0x3f3f3f3f#define inf -0x3f3f3f3f#define lson k<<1, L, mid#define rson k<<1|1, mid+1, R#define mem0(a) memset(a,0,sizeof(a))#define mem1(a) memset(a,-1,sizeof(a))#define mem(a, b) memset(a, b, sizeof(a))typedef long long ll;ll a[1000000];int count1;int main(){    mem0(a);    int m;    for(int i=1;(ll)3*i*(i-1)+1<=1000010000;i++){        a[i]=3*i*(i-1)+1;        m=i;    }    int t;    int n;    scanf("%d",&t);    while(t--){        scanf("%d",&n);        if(*lower_bound(a+1,a+m+1,n)==n){            printf("1\n");            continue;        }        int p=1;        int flag=0;        if((n-2)%6==0){                             //两个如果可能的话,则 (n-2)%6==0;             while(2*a[p]<=n){                if(*lower_bound(a+1,a+m+1,n-a[p])==n-a[p]){                    printf("2\n");                    flag=1;                    break;                }                p++;            }        }        if(flag==1)            continue;        for(int i=3;;i++){            if((n-i)%6==0){                printf("%d\n",i);                break;            }        }    }    return 0;}
0 0
原创粉丝点击