貪心+高精度【洛谷P1080】
阿新 • • 發佈:2018-11-10
此篇文章的程式碼來自@Chlience,未經允許私自借用,十分不好意思。
題目連結:https://www.luogu.org/problemnew/show/P1080
拿到這個題目,我根本沒有注意到資料範圍竟然會超long long,真的是第一次做這種貪心題竟然需要寫高精度。(做的題太少了,所以沒見過,所以蒻)
首先推導一下貪心的策略:(借鑑自@Chlience)
簡化一下問題,假如只有國王和兩個大臣,總共三個人:如下圖
king | a0 | b0 |
p1 | a1 | b1 |
p2 | a2 | b2 |
此時ans1 = max(a0/b1,(a0*a1)/b2)
king | a0 | b0 |
p2 |
a2 | b2 |
p1 | a1 | b1 |
此時ans2 = max(a0/b2,(a0*a2)/b1)
顯然可以化簡為ans1 = max(k1,k2)
ans2 = max(k3,k4)
則有 k2>k3, k4>k1
若ans1<ans2
則 k4>k2
則 (a0*a2)/b1>(a0*a1)/b2
變換得:a1*b1<a2*b2
至此,我們得出了cmp()函式的寫法。
然後,在此奉上@Chlience的程式碼:
#include <bits/stdc++.h> using namespace std; int now[20010],sum[20010],ans[20010],add[20010]; struct Node { int a; int b; long long a_b; }node[1010]; void times(int x) { memset(add,0,sizeof(add)); for(int i=1;i<=ans[0];i++) { ans[i]=ans[i]*x; add[i+1]+=ans[i]/10; ans[i]%=10; } for(int i=1;i<=ans[0]+4;i++) { ans[i]+=add[i]; if(ans[i]>=10) { ans[i+1]+=ans[i]/10; ans[i]%=10; } if(ans[i]!=0) { ans[0]=max(ans[0],i); } } return ; } int divition(int x) { memset(add,0,sizeof(add)); int q=0; for(int i=ans[0];i>=1;i--) { q*=10; q+=ans[i]; add[i]=q/x; if(add[0]==0 && add[i]!=0) { add[0]=i; } q%=x; } return 0; } bool compare() { if(sum[0]==add[0]) { for(int i=add[0];i>=1;i--) { if(add[i]>sum[i]) return 1; if(add[i]<sum[i]) return 0; } } if(add[0]>sum[0]) return 1; if(add[0]<sum[0]) return 0; } void cp () { memset(sum,0,sizeof(sum)); for(int i=add[0];i>=0;i--) { sum[i]=add[i]; } return ; } bool cmp(Node a,Node b) { return a.a_b<b.a_b; } int main() { int n; cin>>n; for(int i=0;i<=n;i++) { cin>>node[i].a>>node[i].b; node[i].a_b=node[i].a*node[i].b; } sort(node+1,node+n+1,cmp); ans[0]=1,ans[1]=1; for(int i=1;i<=n;i++) { times(node[i-1].a); divition(node[i].b); if(compare()) { cp(); } } for(int i=sum[0];i>=1;i--) printf("%d",sum[i]); return 0; }
自己還是太蒻了,高精度板子會寫(抄),放在實際的應用裡面就一團亂。