【题解】T6775 拆数乘积

来源:互联网 发布:arpu值算法 编辑:程序博客网 时间:2024/06/06 15:34

原题链接

算法分析

要想 AC 此题,就先要用简单的数论和贪心找到最优解的组成方法。
以 2004 为例,由于把 2004 拆分成若干个互不相等的自然数的和的分法只有有限种,因而一定存在一种分法,使得这些自然数的乘积最大。
若 1 作因数,则显然乘积不会最大。把 2004 拆分成若干个互不相等的自然数的和,因数个数越多,乘积越大。为了使因数个数尽可能得多,我们把 2004 分成 2+3…+n 直到和大于等于 2004 。
若和比 2004 大 1,则因数个数至少减少 1 个,为了使乘积最大,应去掉最小的 2,并将最后一个数(最大)加上 1 。
若和比 2004 大 k(k ≠ 1),则去掉等于k的那个数,便可使乘积最大。
例如 15,s = 2+3+4+5+6,刚好大于 15,s - 15 = 5,所以把 5 去掉。
又例如 13,s = 2+3+4+5,刚好大于 13,s - 13 = 1,所以去掉 2,并把 5 加 1 ,即 3 4 6 。

示例代码

#include <iostream>using namespace std;int n , sum , ans[10001] , c = 1;//ans数组用来存拆分出来的数int main(){    ios::sync_with_stdio(0);    cin >> n;    if ( n <= 4 )//特判,如果n小于等于4,自己本身就是最优解    {        cout << n;        return 0;    }    for ( int i = 2 ; i <= n ; i++ )//2到n循环    {

if ( n >= i ){ n -= i;//每拆分出1个数,n就减去这个数 ans[c++] = i;//把i存下来 } else break;//不能再拆分就终止循环 } for ( int i = c - 1 ; i >= 1 ; i-- )//逆序倒推 if ( n > 0 ) ans[i]++ , n--;//多的数分担给其他数 if ( n > 0 ) ans[c-1]++;//如果还多,就分给最后一个数 for ( int i = 1 ; i < c ; i++ ) cout << ans[i] << " ";//输出每一个拆分出来的数 return 0;}



原创粉丝点击