1. 程式人生 > >【UOJ#21】【UR#1】縮進優化

【UOJ#21】【UR#1】縮進優化

splay freopen logs img hide ssi 答案 div char

我好弱啊,什麽題都做不出來QAQ

原題:

小O是一個熱愛短代碼的選手。在縮代碼方面,他是一位身經百戰的老手。世界各地的OJ上,很多題的最短解答排行榜都有他的身影。這令他感到十分愉悅。

最近,他突然發現,很多時候自己的程序明明看起來比別人的更短,實際代碼量卻更長。這令他感到很費解。經過一番研究,原來是因為他每一行的縮進都全是由空格組成的,大量的空格讓代碼量隨之增大。

現在設小O有一份 n 行的代碼,第 i 行有 ai 個空格作為縮進。

為解決這一問題,小O要給自己文本編輯器設定一個正整數的默認TAB寬度 x,然後對於每一行,編輯器從頭至尾不斷把連續 x 個空格替換成一個TAB,直到剩余空格數不足

x 個。

最終縮進所占代碼量為空格數與TAB數的和。請你幫小O選擇一個合適的 x,使得縮進所占代碼量最小。

n,ai<=10^6

技術分享

恩一個比較簡單的思路是枚舉塊的大小,然後暴力計算答案,令M為最大的aiO(nM)可以拿到20分

然後發現暴力計算的時候相同的ai可以合並起來,這樣可以搞成O(M^2)的因為有兩個點M比較小n比較大所以可以拿到40分

如果tab的長度是x那麽沒多換一個tab就減少x-1個空格,所以最終答案是n-(x-1)*Σai/x,接下來最大化(x-1)*Σai/x

還是枚舉x,每次計算Σai/x,直接計算不太好算,就枚舉ai/x的值,在輸入ai後用sj記錄ai==j的有多少個,枚舉ai/x的值後就可以快速通過s計算個數再乘上ai/x這個值得到結果

有一個結論,Σ_{i=1}^{n}1/i=O(logn)

所以這個做法最終是O(MlogM)的,就可以ac辣

我好弱啊,NOI怎麽玩嘛QAQ

代碼:

技術分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long
 8 const ll inf=(ll)2e18;
 9 int rd(){int
z=0,mk=1; char ch=getchar(); 10 while(ch<0||ch>9){if(ch==-)mk=-1; ch=getchar();} 11 while(ch>=0&&ch<=9){z=(z<<3)+(z<<1)+ch-0; ch=getchar();} 12 return z*mk; 13 } 14 int n,a[1100000]; int mx=0; 15 ll s[1100000]; 16 ll ans=0; 17 int main(){freopen("ddd.in","r",stdin); 18 cin>>n; 19 for(int i=1;i<=n;++i) a[i]=rd(),mx=max(mx,a[i]),++s[a[i]]; 20 for(int i=1;i<=mx;++i) s[i]+=s[i-1]; 21 for(int i=1;i<=mx;++i){ 22 int jjj=mx/i; ll bwl=0; 23 for(int j=1;j<=jjj;++j) bwl+=(s[(j+1)*i-1>mx?mx:(j+1)*i-1]-s[j*i-1])*j; 24 ans=max(ans,(i-1)*bwl); 25 } 26 ll bwl=0; 27 for(int i=1;i<=n;++i) bwl+=a[i]; 28 cout<<bwl-ans<<endl; 29 return 0; 30 }
View Code

【UOJ#21】【UR#1】縮進優化