标签:
这个题看上去是一个贪心, 但是这个贪心显然是错的. 事实上这道题目很简单, 先判断1个是否可以, 然后判断2个是否可以. 之后找到最小的k(k>2), 使得(m?k)mod6=0即可.
证明如下: 3n(n?1)+1=6(n?(n?1)/2)+1, 注意到n?(n?1)/2是三角形数, 任意一个自然数最多只需要3个三角形数即可表示. 枚举需要k个, 那么显然m=6(k个三角形数的和)+k, 由于k≥3, 只要m?k是6的倍数就一定是有解的.
事实上, 打个表应该也能发现规律.
学了下三角形数的性质:
1.任意一个数都可以由三个三角形术表示
2.任何三角形数 * 8 + 1得到一个平方数
3.验证三角形数的公式:
n = (sqrt ( 8 * X + 1 ) - 1) / 2
如果为三角形数那么n为整数切为第n个
三角数具体连接:http://baike.baidu.com/view/1047488.htm
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn = 100000; const int INF = 1000000000; int _list[maxn],cnt = 1,n; void init(){ while(1){ _list[cnt] = 3 * cnt * (cnt - 1) + 1; if(_list[cnt] > INF) break; cnt ++; } } int Find(int value){ return lower_bound(_list + 1,_list + cnt,value) - _list; } bool solve(int v){ int l = 1,r = Find(v); while(l <= r){ if(_list[l] + _list[r] > v) r --; else if(_list[l] + _list[r] < v) l ++; else return true; } return false; } bool can(int n){ int d = (n - 1); if(d % 6 == 0){ d /= 6; double dd = (sqrt(8.0 * d + 1.0) - 1.0) / 2; if(dd == (int)dd) return true; } return false; } int main(){ init(); int T; scanf("%d",&T); while(T--){ scanf("%d",&n); /* 这里说一下,如果暴力找的话时间话费46ms 如果利用判断是否为三角数的性质时间为31ms */ /*if(_list[Find(n)] == n){ printf("1\n"); }*/ if(can(n)){ printf("1\n"); } else{ if((n - 2) % 6 == 0 && solve(n)) printf("2\n"); else{ for(int i = 3; ; i++) if((n - i) % 6 == 0){ printf("%d\n",i); break; } } } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/u013451221/article/details/47087247