[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<int, int> 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;} |

浙公网安备 33010602011771号