description有n棵竹子,初始時每棵竹子高度都是0,每棵竹子每天長高1m這道題我還愣是問大佬問了好久才搞懂。對於每棵竹子,我們不希望其高度超過a[i],如果超過了,我們就會把超過的部分減去
奇怪的是減去之後竹子就不會再長了
我們不希望每天去看一下竹子的情況,希望每隔d天去看一下竹子的情況
本著愛護環境的原則,我們不希望減去的竹子長度之和大於k
我們最多可以隔多少天去看一次竹子?
input
第一行兩個整數n,k
第二行n隔整數表示a[i]
output
乙個整數表示答案,即最大的d值
hint
20%:ai<=5*10^5
另有20%:k<=1
100%:1<=n<=100,0<=k<=10^11,1<=ai<=10^9
第一眼:而不是二分嘛,水!結果考試快結束是才反應過來這答案並不滿足二分的性質。如:4 4 4,d選4比選3優。
那麼怎麼辦呢?
首先可以明確,d一定小於a[i]的最大值。那麼這個d就太多了啊。如果直接暴力去for d,肯定是不行的,只能得20分。我們希望可以減少一些無用的d的列舉。
先可以得到公式:
轉化一下:
我們可以發現,對於[ai/d]向上取整,有多個d對應相同的值。如:10/d,d=5,6,7,8,9都對應乙個值2,可以證明d的數量是o(√n)
我們記錄每乙個ai對應的d,其中d可以代表一系列d。在算出了sigma([ai/d])後,可以根據上面的公式求出最大的d
暴力列舉得出的d,複雜度o(n*ai^0.5)
詳情看**吧。。。解釋起來好麻煩。。
#include
#include
#include
#define ll long long
using namespace std;
const int n=105;
const int m=100000+5;
ll a[n],n,k,c=0;
ll ans=0,tot=0,vec[n*m],cnt=0;
int main()
c+=k;
sort(vec+1,vec+cnt+1);
cnt=unique(vec+1,vec+cnt+1)-(vec+1);
for(int i=1;i<=cnt;i++)
printf("%lld",ans);
return
0;}
總結:
1、在想二分時可以舉例子來驗證答案的單調性
2、把公式寫出來時,可以結合一些數論的知識,看看能不能化簡
CodeForces 830C 奇怪的降複雜度
description有n棵竹子,初始時每棵竹子高度都是0,每棵竹子每天長高1m 對於每棵竹子,我們不希望其高度超過a i 如果超過了,我們就會把超過的部分減去 奇怪的是減去之後竹子就不會再長了 我們不希望每天去看一下竹子的情況,希望每隔d天去看一下竹子的情況 本著愛護環境的原則,我們不希望減去的竹...
Codeforces830A 二分 貪心
二分其實很好考慮對吧,時間越多,滿足的越多,如何judge呢,這個仔細想想還是挺有意思的.1.左邊的人拿左邊的鑰匙能在這個時間段滿足,那就滿足,對於整體方案來說是最優的 2.如果左邊的對於某把鑰匙不滿足,之後出現了某個位置鑰匙滿足,那麼之前那把鑰匙一定是在這個人的左邊,那麼進而證明右邊的人也一定不會...
c 奇階幻方
奇階幻方的產生規則 將1放在第一行中間一列 從2開始直到n n止各數依次按下列規則存放 按 45 方向行走,如向右上 每乙個數存放的行比前乙個數的行數減1,列數加1 如果行列範圍超出矩陣範圍,則迴繞。如果按上面規則確定的位置上已有數,或上乙個數是第1行第n列時,include include usi...