known Numbers(数论+二分+贪心+构造)

题目链接:

codeforces 225B

题目大意:

定义f(k,n)为类似菲波那契数推导,只不过变为前k项的和,然后给出一个数s,利用k-菲波那契数构造出一个不重复的集合的元素和为s,集合的规模大于1

题目分析:首先因为菲波那契数的增长速度快的吓人,所以给的数据范围很快就能达到,我们得到O(n)的构造出所有的可能用到的k-菲波那契数是可行的。然后就是构造如何构造的问题了。 因为题目保证解一定存在,那么我们考虑如何构造一组可行解,采取的是贪心的方法,先选取能够选择的元素中最大的。如果答案的集合只有1个元素,那么我们添上0保证得到的解的规模

这样如果对于给定数s的一个因数是数列中的数位置为n,倍数等于2,那么我们通过选取f(k,,n+1)能够保证有合法解避免这种同一个数出现多次的冲突,找到最大的那个数,因为那个数不可能出现当前的s是它的两倍,因为sAC代码:;LL;LL a[MAX];int s,k,n;multiset<int,greater<int> > col;vector<int> ans;int main ( ){while (~scanf ( “%d%d” , &s , &k ) ){col.clear();ans.clear();memset ( a , 0 , sizeof ( a ) );n = 1;a[1] = 1;a[0] = 0;while ( a[n]-a[n-1] <= s ){int l = max ( n-k , 0 );a[n+1] = a[n]-a[l];col.insert ( a[n+1] );a[n+1] += a[n];n++;}multiset<int>::iterator it;/*cout << “——————————” << endl;//multiset<int>::iterator it;for ( it = col.begin() ; it != col.end() ; it++ )cout << *it << endl;cout << “—————————” << endl;*/while ( s ){it = col.lower_bound ( s );s -= *it;ans.push_back ( *it );col.erase ( it );}while ( k!= 1 && ans.size() < 2 ) ans.push_back ( 0 );printf ( “%d\n” , (int)ans.size() );for ( int i = 0 ; i < ans.size() ; i++ )printf ( “%d ” , ans[i] );puts (“”);}}

告诉自己,我这次失败了,重新开始吧!下次我会吸取教训,不让自己犯同样的错误的

known Numbers(数论+二分+贪心+构造)

相关文章:

你感兴趣的文章:

标签云: