标签:
题目链接:点击打开链接
这个题看上去是一个贪心, 但是这个贪心显然是错的. 事实上这道题目很简单, 先判断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的倍数就一定是有解的.
事实上, 打个表应该也能发现规律.
求k==1时用二分找出结果求k==2时,对于一个有序的数组,求两个值的和是不是n,用两个指针,一个指向头,一个指向为,不断向另一个方向逼近,就可以找到是否存在和为n
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; int a[21000] ; void init() { for(int i = 1 ; i <= 20000 ; i++) { a[i] = 3*i*(i-1)+1 ; } } int binSearch(int x,int high){ int low = 1 , mid , k ; while( low <= high ) { mid = (low+high)/2 ; if( a[mid] <= x ) { k = mid ; low = mid + 1 ; } else high = mid - 1 ; } return k ; } int main() { int t , m , n , k , i , j , l , r ; init() ; scanf("%d", &t) ; while( t-- ) { scanf("%d", &m) ; n = binSearch(m,20000) ; if( a[n] == m ) { printf("1\n") ; continue ; } l = 1 ; r = n ; while( l <= r ) { if( a[l]+a[r] == m ) break ; if( a[l]+a[r] < m ) l++ ; else r-- ; } if( l <= r ) { printf("2\n") ; continue ; } k = 3 ; while( 1 ) { if( (m-k)%6 == 0 ) break ; else k++ ; } printf("%d\n", k) ; } return 0 ; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/winddreams/article/details/47086135