HDU5312 Sequence

来源:互联网 发布:阿里双11实时数据 编辑:程序博客网 时间:2024/05/16 17:37

题意:t组数据,每组数据给个m,问m最少能由几项形如3*n*(n-1)+1的数表示

eg 7=1(n=1)+1(n=1)+1(n=1)+1(n=1)+1(n=1)+1(n=1)+1(n=1);

     7=7(n=2);

     所以7最少能由1个数表示


分析:3*n*(n-1)+1可以转换为6*(n*(n-1)/2)+1,而n*(n-1)/2是一个三角形数,设为An,

   则m可以表示为m=6*(A1+A2+…+Ak)+k(假设m最少能由k个数表示)看,由三   角形数的性质(一个自然数最多能由三个三角形数表示)可得,当k>=3时,A1+…    +Ak可以表示任意自然数,此时k=(m-1)%6+1+6*n(n=0,1,2,…)(A1+A2+…Ak  是自然 数)此时最小值k取n=0,即k=(m-1)%6+1(k>=3).另外,如果当n=0时,  k的值为1或者2,此时需要考虑是否存在一个或者两个三角形数能表示出   该数m,如果可以,则k的最小值即为1或者2,如果不可以,则取n=1,  k+=6;

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<map>#include<iostream>using namespace std;const int maxn = 1e6+5;map<int,int>Map;int v[maxn];int main(){    int t;    for(int i=1;i<=100000;i++){ //预处理        int tmp=3*i*(i-1)+1;        if(tmp>1e9) break;        v[i]=tmp;        Map[tmp]=1;             //用于后面查看此数是否能够由3*n*(n-1)+1表示    }    scanf("%d",&t);    while(t--)    {        int n;        scanf("%d",&n);        int k=(n-1)%6+1;        //(n-1)%6+1==n%6=0?6:n%6,两种写法都可以        if(k>=3){               //k>=3,此时一定存在自然数能由A1+…Ak的数表示            printf("%d\n",k);        }        else if(k==1){          //k==1 检验n是否能由该式子表示            if(Map.count(n)) printf("1\n");            else printf("7\n");        }        else if(k==2){          //k==2,检验n是否能由两个该式子的数表示            int flag=0;            for(int i=1;v[i]<=n/2;i++){                if(Map.count(n-v[i])) flag=1;            }            if(flag) printf("2\n");            else printf("8\n");        }    }}







1 0
原创粉丝点击