11091 最優自然數分解問題(貪心)
11091 最優自然數分解問題
時間限制:1000MS 記憶體限制:65535K
提交次數:0 通過次數:0
題型: 程式設計題 語言: C++;C;VC;JAVA
Description
問題描述:設n是一個正整數。 (1)現在將n分解為若干個互不相同的自然數之和,且使這些自然數的乘積最大。 (2)現在將n分解為若干個自然數之和,且使這些自然數的乘積最大。 程式設計任務:對於給定的正整數n,程式設計計算問題(1)和(2)的最優分解的最大乘積。 注意: 1. 這裡的自然數不含0但允許為1。 2. 特別地,當整數n無法分解為若干互不相同的加數時,即自身視為單獨的一個加數,比如輸入2,問題(1)的解輸出為2。 而如果整數n可以分解為若干互不相同的加數時,不考慮自身為單獨加數的情況,比如4,問題(1)的解輸出為3,而非4。 3. 若干互不相同自然數或若干自然數,這個若干可>=1,也就是可以為1。
輸入格式
只有一個正整數n(1<=n<=100)。
輸出格式
輸出待解問題(1)和(2)的最大乘積,中間空格相連,這兩個數可能較大請皆用64位整數。 如,輸入n為10,若加數互不相同,則n=2+3+5,此時最大乘積為2*3*5=30。 若加數可相同,則n=2+2+3+3,此時最大乘積為2*2*3*3=36。
輸入樣例
10
輸出樣例
30 36
提示
分析: 注意無論是(1)還是(2),乘積皆用64位整數表示。 (1)分解為互不相同自然數之和 注意到: 若a+b等於一個常數,則|a-b|越小,ab就越大。 要使得加數互不相同,又儘可能集中,那加數只能是連續的自然數了。 貪心策略:將n分成從2開始的連續的自然數的和。如果最後剩下一個數,將此剩餘數在後項優先的方式下均勻地分給前面各項。 (2)分解為若干自然數之和 注意到: 若a+b等於一個常數,則|a-b|越小,ab就越大。 若 n = m1+m2+...+mk,則 -1 <= (mi-mj) <= 1,(1<=i<=k, 1<=j<=k),即任意加數的差距不超過正負1。 由於拆分的加數可以相同,任何一個數拆後乘積總比不拆強,因此拆到極盡,極盡的加數為3或2,且拆為3比拆為2好,因此優先拆為3。 貪心策略: 極盡拆解,儘可能先將n拆成3,3,3,...,3;若拆成若干3後還有剩餘,則為2,或2和2。 歸納公式如下: 1)max{m1*m2*...*mk} = 3^(n/3) if n(mod 3)等於0 2)max{m1*m2*...*mk} = 4*3^[(n-4)/3] if n(mod 3)等於1 3)max{m1*m2*...*mk} = 2*3^[(n-2)/3] if n(mod 3)等於2 另外此題所涉的64位整數,如何使用? 編譯環境不同,對64位整數的定義和輸入輸出略有不同: 1) gnu gcc/g++ 中long long型別,或unsigned long long, 輸入輸出用cin和cout直接輸出,用scanf和printf也可以的(但本OJ系統不支援!)。 long long a; cin >> a; cout << a; 也可以使用:(注意一下,本OJ系統的gcc/g++不支援64位整數以"%I64d"形式輸出, 但標準gnu gcc是支援如下的,在codeblocks上可以無誤執行) long long a; scanf("%I64d",&a); printf("%I64d",a); 2) VC中用__int64型別,或unsigned __int64 __int64 a; scanf("%I64d",&a); printf("%I64d",a); vc下,64整數不要用cin和cout來輸入輸出,據說vc下64位整數相容不好,會出錯!大家可測試一下如下程式在vc下是否會出錯? __int64 a; cin >> a; cout << a;
作者
zhengchan
我的實現程式碼:
#include <iostream> #include <math.h> using namespace std; /* 測試資料: 1 2 3 4 10 30 */ int main() { int n; cin >> n; if(n == 1 || n == 2) { // 排除n=1,2的情況 cout << n << " " << n; }else{ // 互不相同自然數之和 long long _res1 = 1; if (n == 3 || n == 4) { // 排除n=3,4的情況 _res1 = n - 1; }else{ int _count = 0; int _rest = 0,_avg = 0,_mod = 0; int a[n + 1];// a[0] 和 a[1]未使用 for(int i = 2; i <= n; i++){ // 初始化a a[i] = 1; } for(int i = 2; i <= n; i++) { _count += i; if(_count > n) { _rest = n - (_count - i);// 多出來的部分 if (_rest < (i - 2)) {// 不夠每個已選的數都分到1 _avg = 1; _mod = 0; }else{// 每個已選的數至少能分到1 _avg = _rest / (i - 2);// 平均分個前i - 2個已確定的數 _mod = _rest % (i - 2);// 平均分後剩下的 } for(int j = i - 1; j >= i - _rest; j--){ // 從後往前分配多出來的部分 a[j] += _avg; } a[i-1] += _mod;//最後一位+_mod break; } a[i] = i; } for(int i = 2; i <= n; i++) { _res1 *= a[i]; } } //若干自然數之和 /* 歸納公式如下: 1)max{m1*m2*...*mk} = 3^(n/3) if n(mod 3)等於0 2)max{m1*m2*...*mk} = 4*3^[(n-4)/3] if n(mod 3)等於1 3)max{m1*m2*...*mk} = 2*3^[(n-2)/3] if n(mod 3)等於2 */ long long _res2 = 1; if(n % 3 == 0){ _res2 = pow(3,n/3); }else if(n % 3 == 1){ _res2 = 4*pow(3,(n-4)/3); }else{ _res2 = 2*pow(3,(n-2)/3); } cout << _res1 << " " << _res2; } cout << endl; return 0; }
相關推薦
11091 最優自然數分解問題(貪心)
11091 最優自然數分解問題 時間限制:1000MS 記憶體限制:65535K 提交次數:0 通過次數:0 題型: 程式設計題 語言: C++;C;VC;JAVA Description 問題描述:設n是一個正整數。 (1)現在將n分解為若干個互不相
最優裝載問題(貪心)
問題簡述:給出n個物體,第i個物體重量為wi。選擇儘量多的物體,是的總重量不超過C。 分析:最簡單的一種了,排序,依次選擇每一個物體,直到無法裝下為止。 附程式碼如下: #include <bits/stdc++.h> using namespace std;
最優分解(貪心)
Description:設n是一個正整數。現要求將n分解為若干個自然數的和,且使這些自然數的乘積最大。對於給定的正整數n,程式設計計算最優分解方案。 Sample Input: 10 Sa
最優裝載問題(貪心基礎)
最優裝載問題。給出n個物體,第i個物體重量為w[i]。選擇儘量多的物體,使得總重量不超過C。 【分析】 由於只關心物體的數量,所有裝重的沒有裝輕的划算。只需把所有物體按重量從小到大排序,一次
最優裝載問題(貪心法)
問題描述: 有一批集裝箱要裝上一艘載重量為c的輪船。其中集裝箱i的重量為Wi。最優裝載問題要求確定在裝載體積不受限制的情況下,將盡可能多的集裝箱裝上輪船。 問題可以描述為: 式中,變數xi = 0 表示不裝入集裝箱 i,xxi = 1 表示裝入集裝箱 i。
最下的串(貪心)
題的大概意思是: 輸入一個字串的長度大小,然後輸入字串,首先分別選取字串的首尾兩個字元,進行字典序比較,將較小的放到新建立的字串的後面,直到原本的字串長度為0。這種思想適合貪心演算法,每選一步就選
CCF之最優配餐(java)
試題編號: 201409-4 試題名稱: 最優配餐 時間限制: 1.0s 記憶體限制: 256.0MB 問題描述: 問題描述 棟棟最近開了一家餐飲連鎖店,提供外賣服務。隨著連鎖
最優分解(貪心演算法)
#include<stdio.h> #include<stdlib.h> int main(){ int n,i,sum=0; int diff,result,j=0; scanf("%d",&n); int *arr = (int
POJ 3621 Sightseeing Cows(最優比例環+SPFA檢測)
span fort exp ros 說明 6.0 lines choice stdio.h Sightseeing Cows Time Limit: 1000MS Memory Limit: 65536K Total Submission
ZOJ——Copying Books 最大值最小化問題 (貪心 + 二分)
題目連結: #include <cstdio> #include <cmath> #include<vector> #include<cstring> #include<algorithm> #include<cmath>
Qin Shi Huang's National Road System 【HDU - 4081】【次優比例生成樹(最優比例生成樹變形)】
題目連結 題目問的是有N個點集,問你建立N-1條邊的情況下,使得路徑最短的方案數,但是呢,題目中又給出徐福會魔法可以把一條路徑變成免費道路,但是有個限制就是希望這條路上兩個城市的人口數比上除去該路徑以外整棵樹的權值能最大。 一開始就想到的是最優比例生成樹,但是
1065 最小正子段和(貪心)
1065 最小正子段和 1 秒 131,072 KB 20 分 3 級題 思路: 一開始以為是動態規劃,但是求的是大於0的子段和,那麼只能暴力求解了 預處理資料,儲存為字首和陣列,然後進行排序,在這之前需要儲存排序前的位置d[i] 然後最重要的,迴圈排完的陣列a[i] 判斷 a[i]-a[i-1]&
hdu 5969 最大的位或(貪心)
對於一個l和r 我們都看成2進位制 最優情況一定是1000和0111來異或這樣就能得到在位數不可能改變的情況下能夠得到的最大值, 那麼如果l到r能夠存在這種情況就這麼異或 但如果l和r的
最小支配集,最小點覆蓋,最大獨立集(貪心/DP)
最小支配集(minimal dominating set):對於圖G=(V,E)來說,設V'是圖G的一個支配集,則對於圖中的任意一個頂點u,要麼屬於集合V',要麼與V'中的頂點相連。 在V'中除去任何元素後V'不再是支配集,則支配集V'是極小支配集。稱G中所有支配集中頂點個
石油主管道最優位置問題(平均時間為線性時間)C++實現
// 石油主管道最優位置問題.cpp : Defines the entry point for the console application. //公司計劃建設一條從西到東石油主管道,它穿過一個
隨手練——HDU-5969 最大的位或 (貪心)
pro esp 數據 .cn main ont 特殊 規律 strong HDU-5969:http://acm.hdu.edu.cn/showproblem.php?pid=5969 一開始也是分了類,覺得要兩種情況,l 與 r 位數相同與不同的情況,仔細想一下,可以一起
POJ 1192 最優連通子集(樹形DP)
最優連通子集 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 3100 Accepted: 1666 Description 眾所周知,我們可以通過直角座標系把平面
最短路徑演算法(一) Dijkstra演算法(貪心演算法)
Dijkstra演算法是由荷蘭電腦科學家狄克斯特拉(Dijkstra)於1959 年提出的,因此又叫狄克斯特拉演算法。是從一個頂點到其餘各頂點的最短路徑演算法,解決的是有向圖中最短路徑問題。其基本原理是:每次新擴充套件一個距離最短的點,更新與其相鄰的點的距離。當所有邊權都為正
CCF201409-4 最優配餐(100分)
試題編號: 201409-4 試題名稱: 最優配餐 時間限制: 1.0s 記憶體限制: 256.0MB 問題描述: 問題描述 棟棟最近開了一家餐飲連鎖店,提供外賣服務。隨著連鎖店越來越多,怎麼合理的給客戶送餐成為了一個急需解決的問題。 棟棟的
BZOJ 3399 [Usaco2009 Mar]Sand Castle城堡(貪心)
castle con name 個數 blank 調整 can 貪心 pro 【題目鏈接】 http://www.lydsy.com/JudgeOnline/problem.php?id=3399 【題目大意】 將一個集合調整成另一個集合中的數,把一個