[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\n", k);

                break;

            }

        }

    }

    return 0;

}

时间: 2024-10-09 19:06:21

[hdu5312]数的拆分,数学推导的相关文章

leetcode 343. Integer Break(dp或数学推导)

Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get. For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 +

HDU 5073 Galaxy(Anshan 2014)(数学推导,贪婪)

Galaxy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 556    Accepted Submission(s): 127 Special Judge Problem Description Good news for us: to release the financial pressure, the government

HDU 5073 Galaxy(Anshan 2014)(数学推导,贪心)

Galaxy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 556    Accepted Submission(s): 127 Special Judge Problem Description Good news for us: to release the financial pressure, the government

时域和频域变换之---傅里叶级数的数学推导

废话不多说先列提纲: 0.概述-需求分析-功能描述-受限和缺点改进+知识点预备 1.泰勒级数和傅里叶级数的本质区别,泰勒展开 2.  函数投影和向量正交 3.两个不变函数求导是本身e^x,sinx,cosx也是为什么要傅里叶转换的原因! 4.傅里叶技术推到过程 5.附录参考资料 0.有些时候,尤其是在图像处理中,矩阵运算数据量太大,特征提取量多,此时可以通过时域转频域来减少计算量,而且此转换不会损失数据完整性. 时域转频域的方法有周期函数用傅里叶技术,非周期函数(没有间断点的函数)用傅里叶转换,

Codeforces Round #360 (Div. 2) D 数学推导 E dp

Codeforces Round #360 (Div. 2) A  == B  水,但记一下: 第 n 个长度为偶数的回文数是  n+reverse(n). C    dfs 01染色,水 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i

HDU1719 Friend (数学推导)

friend numbers = 2^x + 3^y -1 1 #include<stdio.h> 2 int main() 3 { 4 __int64 a; 5 while(scanf("%I64d",&a)!=EOF) 6 { 7 if(!a) 8 { 9 printf("NO!\n"); 10 continue; 11 } 12 a+=1; 13 while(a%2==0||a%3==0) 14 { 15 if(a%2==0) a/=2;

借One-Class-SVM回顾SMO在SVM中的数学推导--记录毕业论文5

上篇记录了一些决策树算法,这篇是借OC-SVM填回SMO在SVM中的数学推导这个坑. 参考文献: http://research.microsoft.com/pubs/69644/tr-98-14.pdf https://inst.eecs.berkeley.edu/~ee227a/fa10/login/l_dual_strong.html https://inst.eecs.berkeley.edu/~ee127a/book/login/l_sdual_slater.html http://w

最大熵模型中的数学推导

最大熵模型中的数学推导 查看原文,点击这里 0 引言 写完SVM之后,一直想继续写机器学习的系列,无奈一直时间不稳定且对各个模型算法的理解尚不够,所以导致迟迟未动笔.无独有偶,重写KMP得益于今年4月个人组织的算法班,而动笔继续写这个机器学习系列,正得益于今年10月组织的机器学习班. 10月26日机器学习班第6次课,身为讲师之一的邹博讲最大熵模型,他从熵的概念,讲到为何要最大熵.最大熵的推导,以及求解参数的IIS方法,整个过程讲得非常流畅,特别是其中的数学推导.晚上我把他的PPT 在微博上公开分

acdream.18.KIDx&#39;s Triangle(数学推导)

KIDx's Triangle Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description One day, KIDx solved a math problem for middle students in seconds! And than he created this problem. N