uva 1614奇怪的股市(歸納法證明,貪心)

2022-05-06 16:21:08 字數 1032 閱讀 8132

輸入乙個長度為n的序列a,滿足\(1\le a_i\le i\),要求確定每個數的正負號,使得所有數的總和為0.例如a=,則4個數的符號分別是1, -1, -1, 1即可。但若a=,則無解。n<=1e5。

這道題相當於要找到兩堆相等的數。若序列中數的總和為奇數,那麼拆出來的兩堆數無論如何都不可能相等,所以無解。由於這道題的特殊性質,可用歸納法證明總和為偶數時一定有解。

現在要證明,用前i個數的全部或部分可以湊出0到sum[i]的所有整數。n=1時這是成立的。假設n=k之前所有項都成立,那麼\(sum[k+1]=sum[k]+a[k+1]\)。只需證明能湊出\(sum[k]+1\)到\(sum[k]+a[k+1]\)的所有整數即可。由於\(1\le a_[k+1]\le k+1\),而\(sum[k]\ge k\),所以\(sum[k]+p=x+a[k+1]\ (1\le p\le a[k+1],0\le x\le sum[k])\)恆成立。

這樣一來,就證明了用前n個數,可以湊出sum[n]/2。當sum[n]是偶數時,另一半也就是sum[n]/2。現在的問題就是找出和等於sum[n]/2的數。直接將a陣列從大到小排序,然後貪心的取即可。

為什麼貪心的取是正確的呢?因為\(1\le a_i\le i\),排序完的陣列必定也滿足這個條件。所以只要貪心的取顯然有解。

#include #include using namespace std;

const int maxn=1e5+5;

struct nodea[maxn];

int n, chose[maxn];

long long sum;

bool cmp1(node &x, node &y)

//100萬才需要讀優

int main() else chose[a[i].id]=-1;

puts("yes");

for (int i=0; iprintf("%d ", chose[i]);

puts("");

}return 0;

}

貪心 Uva1614奇怪的股市

題意 給出乙個長度為n的序列a,滿足1 a i i,給每個數分配乙個正號或負號,求是否能讓這些數加起來為0,如果是輸出每個數的正負 任意方案 題解 如果a陣列每個元素加起來不為2的倍數,就無解 因為正負號不會影響奇偶 若當前沒被判無解,就從後往前掃一遍,記錄乙個sum,如果當前sum 0,那麼給當前...

數學歸納法的正確敘述

證明,對於所有正整數n,p n 為真。歸納法的敘述如下 a 給出p 1 為真的證明。b 給出 如果所有p 1 p 2 p n 都為真,則p n 1 也為真 的證明 這個證明應對任何正整數n都為真。列舉幾種不太完整的敘述 最簡單和常見的數學歸納法證明方法是證明當n屬於所有自然數時乙個表示式成,這種方法...

對數學歸納法的總結

什麼是數學歸納法 數學歸納法的原理1 證明 n 1 時命題成立 2 假設 n m 時命題成立,那麼可以推導出在 n m 1的時候命題也成立.m代表任意自然數 數學歸納法的證明1 2 3 n n n 1 2 等差數列求和公式 第一步 驗證改公式在n 1時成立,即 左邊為1,右邊為1 1 1 2 1,等...