zoukankan      html  css  js  c++  java
  • [hdu5312]数的拆分,数学推导

    题意:给定一个序列,a[n]=3n(n-1)+1,n>=1,求给定的m(m<=1e9)最少可以用几个a里面的数表示(可以重复)

     思路:对答案分类

    (1)假定答案为1,则m必定是a中的某一个数,直接查找即可,复杂度O(logn)

    (2)假定答案为2,则m必定可以拆分成两个a中的数之和,用两指针分别从头和尾向中间扫,判断是否可以构成m,复杂度O(n)

    (3)假定答案大于等于3,设答案为k,即k>=3,则必有m=a[i1]+a[i2]+...+a[ik],由于a[i]=3i(i-1)+1=6[i(i-1)/2]+1,所以有:

     m=6[i1(i1-1)/2+i2(i2-1)/2+...+ik(ik-1)/2]+k                        

    所以(m-k)%6==0恒成立,也就是说如果得出了答案k,那么答案一定满足(m-k)%6==0,这是必要性;当k>=3时,令b=(m-k)/6,因为任意一个自然数最多只需要3个三角形数即可表示,所以b=i1(i1-1)/2+i2(i2-1)/2+...+ik(ik-1)/2恒有解,这是充分性。故答案k需满足k>=3且(m-k)%6==0,由于是求最小个数,k从3枚举到第一次满足(m-k)%6==0即可得到答案。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <algorithm>
    using namespace std;
     
    #define pb push_back
    #define mp make_pair
    #define X first
    #define Y second
    #define all(a) (a).begin(), (a).end()
     
    void readInt(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
    void RI(int&f,R&...r){RI(f);RI(r...);}void RIA(int*p,int*q){int d=p<q?1:-1;
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
     
    typedef pair<intint> pii;
    typedef long long ll;
    typedef unsigned long long ull;
     
    template<typename T>bool umax(T &a, const T &b) {
        return a >= b? false : (a = b, true);
    }
    /* -------------------------------------------- */
     
    vector<int> table;
     
    void init() {
        for (int i = 1; ; i ++) {
            ll buf = 3ll * i * (i - 1) + 1;
            if (buf > 1e9 + 7) break;
            table.pb((int)buf);
        }
    }
     
    bool chk(int x) {
        int l = 0, r = upper_bound(all(table), x - table[0]) - table.begin() - 1;
        while (l < r && table[l] + table[r] != x) {
            l ++;
            while (l < r && table[l] + table[r] > x) r --;
        }
        return table[l] + table[r] == x;
    }
     
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt""r", stdin);
    #endif // ONLINE_JUDGE
        int T;
        cin >> T;
        init();
        while (T --) {
            int x;
            RI(x);
            if (find(all(table), x) != table.end()) {
                puts("1");
                continue;
            }
            if (chk(x)) {
                puts("2");
                continue;
            }
            for (int k = 3; ; k ++) {
                if ((x - k) % 6 == 0) {
                    printf("%d ", k);
                    break;
                }
            }
        }
        return 0;
    }

  • 相关阅读:
    hdu 1280 排序水题
    hdu 3336 KMP+DP (仍不懂)
    懂点PS技巧,你会减少很多痛苦
    ajax返回值中有回车换行、空格的解决方法分享
    windows7系统下让所有文件夹都使用同一种视图的方法
    LINUX常用命令大全归纳篇
    js 运算符
    获取修改父页面元素
    while跟do...while的用法
    jQuery取得select选择的文本与值
  • 原文地址:https://www.cnblogs.com/jklongint/p/4681712.html
Copyright © 2011-2022 走看看