zoukankan      html  css  js  c++  java
  • (BC 一周年) hdu 5312 Sequence

    Sequence

     
     Accepts: 25
     
     Submissions: 1442
     Time Limit: 2000/2000 MS (Java/Others)
     
     Memory Limit: 262144/262144 K (Java/Others)
    问题描述
    Soda习得了一个数列, 数列的第nn (n ge 1)(n1)项是3n(n-1)+13n(n1)+1. 现在他想知道对于一个给定的整数mm, 是否可以表示成若干项上述数列的和. 如果可以, 那么需要的最小项数是多少?
    
    例如, 22可以表示为7+7+7+17+7+7+1, 也可以表示为19+1+1+119+1+1+1.
    输入描述
    输入有多组数据. 第一行有一个整数TT (1 le T le 10^4)(1T104​​), 表示测试数据组数. 然后对于每组数据:
    
    一行包含1个整数 mm (1 le m le 10^9)(1m109​​).
    输出描述
    对于每组数据输出最小花费.
    输入样例
    10
    1
    2
    3
    4
    5
    6
    7
    8
    22
    10
    输出样例
    1
    2
    3
    4
    5
    6
    1
    2
    4
    4

    比赛的时候没做出来.这道题需要用到的一个重要的性质是,任意一个自然数可以表示成至多三个三角形数(1,3,6,10,15.....)的和(orz高斯)然后也有推广到任意自然数可以表示成k个k角形数的和的结论(费马提出了猜想,柯西给了证明)然后官方题解说的比较好:

    这个题看上去是一个贪心, 但是这个贪心显然是错的. 事实上这道题目很简单, 先判断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的倍数就一定是有解的.

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

     另外还有一点,特判一个和两个的情况时,一个的好判断,扫一遍就好了

    两个的话,由于这个数列是递增的,我们可以从两边往中间,算是一个不错的优化,具体见代码.

    /*************************************************************************
        > File Name: code/nv/#ann/1003.cpp
        > Author: 111qqz
        > Email: rkz2013@126.com
        > Created Time: 2015年07月28日 星期二 23时03分09秒
     ************************************************************************/
    
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<map>
    #include<set>
    #include<queue>
    #include<vector>
    #include<stack>
    #define y0 abc111qqz
    #define y1 hust111qqz
    #define yn hez111qqz
    #define j1 cute111qqz
    #define tm crazy111qqz
    #define lr dying111qqz
    using namespace std;
    #define REP(i, n) for (int i=0;i<int(n);++i)
    typedef long long LL;
    typedef unsigned long long ULL;
    const int inf = 0x7fffffff;
    const int N=1E5+7;
    int k,m,f[N];
    void init()
    {
        for ( int i = 1 ; i <N; i++)
        {
        f[i]=3*i*(i-1)+1;
        if (f[i]>1000000000)
        {
            k = i-1;
            break;
        }
        }
    }
    int solve (int x)
    {
        for ( int i = 1 ; f[i]<=x ; i++ )
        {
        if (x==f[i])
            return 1;
        }
        int j = k;
        for ( int i = 1 ; i <= k-1&&f[i]<x ; i++)     //因为数列递增,所以可以这样写.
        {
        while(f[i]+f[j]>x) j--;
        if (f[i]+f[j]==x) return 2;
        }
        for ( int i = 3 ; i <= m ; i++ )
        {
        if ((m-i)%6==0)
            return i;
        }
    }
    int main()
    {
        int T;
        init();
        cin>>T;
        int ans;
        while (T--)
        {
    
        scanf("%d",&m);
        cout<<solve(m)<<endl;
    
        }
    
        return 0;
    }
  • 相关阅读:
    位军营 20190919-4 测试,结对要求
    位军营 20190919-5 代码规范,结对要求
    国内源
    hexo安装-nodejs
    python调用chrome打开指定网址
    生成证书,用于签名Android应用
    cygwin64-安装包管理工具
    Android-删除指定包名的App
    pyqt5加载网页的简单使用
    打包python到exe
  • 原文地址:https://www.cnblogs.com/111qqz/p/4684730.html
Copyright © 2011-2022 走看看