*UOJ#223. 【NOI2016】国王饮水记

$n \leq 8000$的数列,问不超过$m \leq 1e9$次操作后第一个数字最大是多少。操作:选一些数,把他们变成他们的平均值。需要保留$p \leq 3000$位小数,提供了一个小数高精度库。

太长懒得写了。。总之就是个斜率优化DP,然后有奇怪性质

原题解

基本能猜到定理八,十至今没理解QAQ

用前八个定理写了一份被卡精度的代码。就是DP的时候记决策点,然后最后用决策点算答案即可。但DP过程本身精度损得厉害,所以有些点过不了。

  1 // This is an empty program with decimal lib
  2 
  3 #include <stdio.h>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <iostream>
  7 #include <string>
  8 #include <algorithm>
  9 //using namespace std;
 10 
 11 // ---------- decimal lib start ----------
 12 
 13 const int PREC = 3100;
 14 
 15 class Decimal {
 16     public:
 17         Decimal();
 18         Decimal(const std::string &s);
 19         Decimal(const char *s);
 20         Decimal(int x);
 21         Decimal(long long x);
 22         Decimal(double x);
 23         
 24         bool is_zero() const;
 25         
 26         // p (p > 0) is the number of digits after the decimal point
 27         std::string to_string(int p) const;
 28         double to_double() const;
 29         
 30         friend Decimal operator + (const Decimal &a, const Decimal &b);
 31         friend Decimal operator + (const Decimal &a, int x);
 32         friend Decimal operator + (int x, const Decimal &a);
 33         friend Decimal operator + (const Decimal &a, long long x);
 34         friend Decimal operator + (long long x, const Decimal &a);
 35         friend Decimal operator + (const Decimal &a, double x);
 36         friend Decimal operator + (double x, const Decimal &a);
 37         
 38         friend Decimal operator - (const Decimal &a, const Decimal &b);
 39         friend Decimal operator - (const Decimal &a, int x);
 40         friend Decimal operator - (int x, const Decimal &a);
 41         friend Decimal operator - (const Decimal &a, long long x);
 42         friend Decimal operator - (long long x, const Decimal &a);
 43         friend Decimal operator - (const Decimal &a, double x);
 44         friend Decimal operator - (double x, const Decimal &a);
 45         
 46         friend Decimal operator * (const Decimal &a, int x);
 47         friend Decimal operator * (int x, const Decimal &a);
 48         
 49         friend Decimal operator / (const Decimal &a, int x);
 50         
 51         friend bool operator < (const Decimal &a, const Decimal &b);
 52         friend bool operator > (const Decimal &a, const Decimal &b);
 53         friend bool operator <= (const Decimal &a, const Decimal &b);
 54         friend bool operator >= (const Decimal &a, const Decimal &b);
 55         friend bool operator == (const Decimal &a, const Decimal &b);
 56         friend bool operator != (const Decimal &a, const Decimal &b);
 57         
 58         Decimal & operator += (int x);
 59         Decimal & operator += (long long x);
 60         Decimal & operator += (double x);
 61         Decimal & operator += (const Decimal &b);
 62         
 63         Decimal & operator -= (int x);
 64         Decimal & operator -= (long long x);
 65         Decimal & operator -= (double x);
 66         Decimal & operator -= (const Decimal &b);
 67         
 68         Decimal & operator *= (int x);
 69         
 70         Decimal & operator /= (int x);
 71         
 72         friend Decimal operator - (const Decimal &a);
 73         
 74         // These can't be called
 75         friend Decimal operator * (const Decimal &a, double x);
 76         friend Decimal operator * (double x, const Decimal &a);
 77         friend Decimal operator / (const Decimal &a, double x);
 78         Decimal & operator *= (double x);
 79         Decimal & operator /= (double x);
 80         
 81     private:
 82         static const int len = PREC / 9 + 1;
 83         static const int mo = 1000000000;
 84         
 85         static void append_to_string(std::string &s, long long x);
 86         
 87         bool is_neg;
 88         long long integer;
 89         int data[len];
 90         
 91         void init_zero();
 92         void init(const char *s);
 93 };
 94 
 95 Decimal::Decimal() {
 96     this->init_zero();
 97 }
 98 
 99 Decimal::Decimal(const char *s) {
100     this->init(s);
101 }
102 
103 Decimal::Decimal(const std::string &s) {
104     this->init(s.c_str());
105 }
106 
107 Decimal::Decimal(int x) {
108     this->init_zero();
109     
110     if (x < 0) {
111         is_neg = true;
112         x = -x;
113     }
114     
115     integer = x;
116 }
117 
118 Decimal::Decimal(long long x) {
119     this->init_zero();
120     
121     if (x < 0) {
122         is_neg = true;
123         x = -x;
124     }
125     
126     integer = x;
127 }
128 
129 Decimal::Decimal(double x) {
130     this->init_zero();
131     
132     if (x < 0) {
133         is_neg = true;
134         x = -x;
135     }
136     
137     integer = (long long)x;
138     x -= integer;
139     
140     for (int i = 0; i < len; i++) {
141         x *= mo;
142         if (x < 0) x = 0;
143         data[i] = (int)x;
144         x -= data[i];
145     }
146 }
147 
148 void Decimal::init_zero() {
149     is_neg = false;
150     integer = 0;
151     memset(data, 0, len * sizeof(int));
152 }
153 
154 bool Decimal::is_zero() const {
155     if (integer) return false;
156     for (int i = 0; i < len; i++) {
157         if (data[i]) return false;
158     }
159     return true;
160 }
161 
162 void Decimal::init(const char *s) {
163     this->init_zero();
164     
165     is_neg = false;
166     integer = 0;
167     
168     // find the first digit or the negative sign
169     while (*s != 0) {
170         if (*s == '-') {
171             is_neg = true;
172             ++s;
173             break;
174         } else if (*s >= 48 && *s <= 57) {
175             break;
176         }
177         ++s;
178     }
179     
180     // read the integer part
181     while (*s >= 48 && *s <= 57) {
182         integer = integer * 10 + *s - 48;
183         ++s;
184     }
185     
186     // read the decimal part
187     if (*s == '.') {
188         int pos = 0;
189         int x = mo / 10;
190         
191         ++s;
192         while (pos < len && *s >= 48 && *s <= 57) {
193             data[pos] += (*s - 48) * x;
194             ++s;
195             x /= 10;
196             if (x == 0) {
197                 ++pos;
198                 x = mo / 10;
199             }
200         }
201     }
202 }
203 
204 void Decimal::append_to_string(std::string &s, long long x) {
205     if (x == 0) {
206         s.append(1, 48);
207         return;
208     }
209     
210     char _[30];
211     int cnt = 0;
212     while (x) {
213         _[cnt++] = x % 10;
214         x /= 10;
215     }
216     while (cnt--) {
217         s.append(1, _[cnt] + 48);
218     }
219 }
220 
221 std::string Decimal::to_string(int p) const {
222     std::string ret;
223     
224     if (is_neg && !this->is_zero()) {
225         ret = "-";
226     }
227     
228     append_to_string(ret, this->integer);
229     
230     ret.append(1, '.');
231     
232     for (int i = 0; i < len; i++) {
233         // append data[i] as "%09d"
234         int x = mo / 10;
235         int tmp = data[i];
236         while (x) {
237             ret.append(1, 48 + tmp / x);
238             tmp %= x;
239             x /= 10;
240             if (--p == 0) {
241                 break;
242             }
243         }
244         if (p == 0) break;
245     }
246     
247     if (p > 0) {
248         ret.append(p, '0');
249     }
250     
251     return ret;
252 }
253 
254 double Decimal::to_double() const {
255     double ret = integer;
256     
257     double k = 1.0;
258     for (int i = 0; i < len; i++) {
259         k /= mo;
260         ret += k * data[i];
261     }
262     
263     if (is_neg) {
264         ret = -ret;
265     }
266     
267     return ret;
268 }
269 
270 bool operator < (const Decimal &a, const Decimal &b) {
271     if (a.is_neg != b.is_neg) {
272         return a.is_neg && (!a.is_zero() || !b.is_zero());
273     } else if (!a.is_neg) {
274         // a, b >= 0
275         if (a.integer != b.integer) {
276             return a.integer < b.integer;
277         }
278         for (int i = 0; i < Decimal::len; i++) {
279             if (a.data[i] != b.data[i]) {
280                 return a.data[i] < b.data[i];
281             }
282         }
283         return false;
284     } else {
285         // a, b <= 0
286         if (a.integer != b.integer) {
287             return a.integer > b.integer;
288         }
289         for (int i = 0; i < Decimal::len; i++) {
290             if (a.data[i] != b.data[i]) {
291                 return a.data[i] > b.data[i];
292             }
293         }
294         return false;
295     }
296 }
297 
298 bool operator > (const Decimal &a, const Decimal &b) {
299     if (a.is_neg != b.is_neg) {
300         return !a.is_neg && (!a.is_zero() || !b.is_zero());
301     } else if (!a.is_neg) {
302         // a, b >= 0
303         if (a.integer != b.integer) {
304             return a.integer > b.integer;
305         }
306         for (int i = 0; i < Decimal::len; i++) {
307             if (a.data[i] != b.data[i]) {
308                 return a.data[i] > b.data[i];
309             }
310         }
311         return false;
312     } else {
313         // a, b <= 0
314         if (a.integer != b.integer) {
315             return a.integer < b.integer;
316         }
317         for (int i = 0; i < Decimal::len; i++) {
318             if (a.data[i] != b.data[i]) {
319                 return a.data[i] < b.data[i];
320             }
321         }
322         return false;
323     }
324 }
325 
326 bool operator <= (const Decimal &a, const Decimal &b) {
327     if (a.is_neg != b.is_neg) {
328         return a.is_neg || (a.is_zero() && b.is_zero());
329     } else if (!a.is_neg) {
330         // a, b >= 0
331         if (a.integer != b.integer) {
332             return a.integer < b.integer;
333         }
334         for (int i = 0; i < Decimal::len; i++) {
335             if (a.data[i] != b.data[i]) {
336                 return a.data[i] < b.data[i];
337             }
338         }
339         return true;
340     } else {
341         // a, b <= 0
342         if (a.integer != b.integer) {
343             return a.integer > b.integer;
344         }
345         for (int i = 0; i < Decimal::len; i++) {
346             if (a.data[i] != b.data[i]) {
347                 return a.data[i] > b.data[i];
348             }
349         }
350         return true;
351     }
352 }
353 
354 bool operator >= (const Decimal &a, const Decimal &b) {
355     if (a.is_neg != b.is_neg) {
356         return !a.is_neg || (a.is_zero() && b.is_zero());
357     } else if (!a.is_neg) {
358         // a, b >= 0
359         if (a.integer != b.integer) {
360             return a.integer > b.integer;
361         }
362         for (int i = 0; i < Decimal::len; i++) {
363             if (a.data[i] != b.data[i]) {
364                 return a.data[i] > b.data[i];
365             }
366         }
367         return true;
368     } else {
369         // a, b <= 0
370         if (a.integer != b.integer) {
371             return a.integer < b.integer;
372         }
373         for (int i = 0; i < Decimal::len; i++) {
374             if (a.data[i] != b.data[i]) {
375                 return a.data[i] < b.data[i];
376             }
377         }
378         return true;
379     }
380 }
381 
382 bool operator == (const Decimal &a, const Decimal &b) {
383     if (a.is_zero() && b.is_zero()) return true;
384     if (a.is_neg != b.is_neg) return false;
385     if (a.integer != b.integer) return false;
386     for (int i = 0; i < Decimal::len; i++) {
387         if (a.data[i] != b.data[i]) return false;
388     }
389     return true;
390 }
391 
392 bool operator != (const Decimal &a, const Decimal &b) {
393     return !(a == b);
394 }
395 
396 Decimal & Decimal::operator += (long long x) {
397     if (!is_neg) {
398         if (integer + x >= 0) {
399             integer += x;
400         } else {
401             bool last = false;
402             for (int i = len - 1; i >= 0; i--) {
403                 if (last || data[i]) {
404                     data[i] = mo - data[i] - last;
405                     last = true;
406                 } else {
407                     last = false;
408                 }
409             }
410             integer = -x - integer - last;
411             is_neg = true;
412         }
413     } else {
414         if (integer - x >= 0) {
415             integer -= x;
416         } else {
417             bool last = false;
418             for (int i = len - 1; i >= 0; i--) {
419                 if (last || data[i]) {
420                     data[i] = mo - data[i] - last;
421                     last = true;
422                 } else {
423                     last = false;
424                 }
425             }
426             integer = x - integer - last;
427             is_neg = false;
428         }
429     }
430     return *this;
431 }
432 
433 Decimal & Decimal::operator += (int x) {
434     return *this += (long long)x;
435 }
436 
437 Decimal & Decimal::operator -= (int x) {
438     return *this += (long long)-x;
439 }
440 
441 Decimal & Decimal::operator -= (long long x) {
442     return *this += -x;
443 }
444 
445 Decimal & Decimal::operator /= (int x) {
446     if (x < 0) {
447         is_neg ^= 1;
448         x = -x;
449     }
450     
451     int last = integer % x;
452     integer /= x;
453     
454     for (int i = 0; i < len; i++) {
455         long long tmp = 1LL * last * mo + data[i];
456         data[i] = tmp / x;
457         last = tmp - 1LL * data[i] * x;
458     }
459     
460     if (is_neg && integer == 0) {
461         int i;
462         for (i = 0; i < len; i++) {
463             if (data[i] != 0) {
464                 break;
465             }
466         }
467         if (i == len) {
468             is_neg = false;
469         }
470     }
471     
472     return *this;
473 }
474 
475 Decimal & Decimal::operator *= (int x) {
476     if (x < 0) {
477         is_neg ^= 1;
478         x = -x;
479     } else if (x == 0) {
480         init_zero();
481         return *this;
482     }
483     
484     int last = 0;
485     for (int i = len - 1; i >= 0; i--) {
486         long long tmp = 1LL * data[i] * x + last;
487         last = tmp / mo;
488         data[i] = tmp - 1LL * last * mo;
489     }
490     integer = integer * x + last;
491     
492     return *this;
493 }
494 
495 Decimal operator - (const Decimal &a) {
496     Decimal ret = a;
497     // -0 = 0
498     if (!ret.is_neg && ret.integer == 0) {
499         int i;
500         for (i = 0; i < Decimal::len; i++) {
501             if (ret.data[i] != 0) break;
502         }
503         if (i < Decimal::len) {
504             ret.is_neg = true;
505         }
506     } else {
507         ret.is_neg ^= 1;
508     }
509     return ret;
510 }
511 
512 Decimal operator + (const Decimal &a, int x) {
513     Decimal ret = a;
514     return ret += x;
515 }
516 
517 Decimal operator + (int x, const Decimal &a) {
518     Decimal ret = a;
519     return ret += x;
520 }
521 
522 Decimal operator + (const Decimal &a, long long x) {
523     Decimal ret = a;
524     return ret += x;
525 }
526 
527 Decimal operator + (long long x, const Decimal &a) {
528     Decimal ret = a;
529     return ret += x;
530 }
531 
532 Decimal operator - (const Decimal &a, int x) {
533     Decimal ret = a;
534     return ret -= x;
535 }
536 
537 Decimal operator - (int x, const Decimal &a) {
538     return -(a - x);
539 }
540 
541 Decimal operator - (const Decimal &a, long long x) {
542     Decimal ret = a;
543     return ret -= x;
544 }
545 
546 Decimal operator - (long long x, const Decimal &a) {
547     return -(a - x);
548 }
549 
550 Decimal operator * (const Decimal &a, int x) {
551     Decimal ret = a;
552     return ret *= x;
553 }
554 
555 Decimal operator * (int x, const Decimal &a) {
556     Decimal ret = a;
557     return ret *= x;
558 }
559 
560 Decimal operator / (const Decimal &a, int x) {
561     Decimal ret = a;
562     return ret /= x;
563 }
564 
565 Decimal operator + (const Decimal &a, const Decimal &b) {
566     if (a.is_neg == b.is_neg) {
567         Decimal ret = a;
568         bool last = false;
569         for (int i = Decimal::len - 1; i >= 0; i--) {
570             ret.data[i] += b.data[i] + last;
571             if (ret.data[i] >= Decimal::mo) {
572                 ret.data[i] -= Decimal::mo;
573                 last = true;
574             } else {
575                 last = false;
576             }
577         }
578         ret.integer += b.integer + last;
579         return ret;
580     } else if (!a.is_neg) {
581         // a - |b|
582         return a - -b;
583     } else {
584         // b - |a|
585         return b - -a;
586     }
587 }
588 
589 Decimal operator - (const Decimal &a, const Decimal &b) {
590     if (!a.is_neg && !b.is_neg) {
591         if (a >= b) {
592             Decimal ret = a;
593             bool last = false;
594             for (int i = Decimal::len - 1; i >= 0; i--) {
595                 ret.data[i] -= b.data[i] + last;
596                 if (ret.data[i] < 0) {
597                     ret.data[i] += Decimal::mo;
598                     last = true;
599                 } else {
600                     last = false;
601                 }
602             }
603             ret.integer -= b.integer + last;
604             return ret;
605         } else {
606             Decimal ret = b;
607             bool last = false;
608             for (int i = Decimal::len - 1; i >= 0; i--) {
609                 ret.data[i] -= a.data[i] + last;
610                 if (ret.data[i] < 0) {
611                     ret.data[i] += Decimal::mo;
612                     last = true;
613                 } else {
614                     last = false;
615                 }
616             }
617             ret.integer -= a.integer + last;
618             ret.is_neg = true;
619             return ret;
620         }
621     } else if (a.is_neg && b.is_neg) {
622         // a - b = (-b) - (-a)
623         return -b - -a;
624     } else if (a.is_neg) {
625         // -|a| - b
626         return -(-a + b);
627     } else {
628         // a - -|b|
629         return a + -b;
630     }
631 }
632 
633 Decimal operator + (const Decimal &a, double x) {
634     return a + Decimal(x);
635 }
636 
637 Decimal operator + (double x, const Decimal &a) {
638     return Decimal(x) + a;
639 }
640 
641 Decimal operator - (const Decimal &a, double x) {
642     return a - Decimal(x);
643 }
644 
645 Decimal operator - (double x, const Decimal &a) {
646     return Decimal(x) - a;
647 }
648 
649 Decimal & Decimal::operator += (double x) {
650     *this = *this + Decimal(x);
651     return *this;
652 }
653 
654 Decimal & Decimal::operator -= (double x) {
655     *this = *this - Decimal(x);
656     return *this;
657 }
658 
659 Decimal & Decimal::operator += (const Decimal &b) {
660     *this = *this + b;
661     return *this;
662 }
663 
664 Decimal & Decimal::operator -= (const Decimal &b) {
665     *this = *this - b;
666     return *this;
667 }
668 
669 // ---------- decimal lib end ----------
670 
671 int qread()
672 {
673     char c; int s=0; while ((c=getchar())<'0' || c>'9');
674     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s;
675 }
676 #define lld Decimal
677 #define ld long double
678 int n,m,P;
679 #define maxn 8011
680 int a[maxn],sum[maxn];
681 ld f[2][maxn]; short cur=0,p[maxn][maxn];
682 short sta[maxn],top=0;
683 
684 struct Queue
685 {
686     int x; ld y;
687     ld operator * (const Queue b) const {return (y-b.y)/(x-b.x);}
688 }que[maxn]; int head,tail;
689 
690 ld calc(int i,int j) {return (f[cur][j]+sum[i]-sum[j])/(i-j+1);}
691 
692 int main()
693 {
694     n=qread(); m=qread(); P=qread();
695     int a0=qread(); for (int i=1;i<n;i++) a[i]=qread();
696     n--; {int m=0; for (int i=1;i<=n;i++) if (a[i]>a0) a[++m]=a[i]; n=m;}
697     std::sort(a+1,a+1+n); for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
698     
699     for (int i=0;i<=n;i++) f[0][i]=a0;
700     ld ans=a0; short xx=0,yy=n;
701     for (int i=1,to=std::min(n,m);i<=to;i++)
702     {
703         memset(f[cur^1],0,sizeof(f[cur^1]));
704         f[cur^1][i]=(f[cur][i-1]+a[i])/2; p[i][i]=i-1;
705         if (ans<f[cur^1][i]) ans=f[cur^1][i],xx=i,yy=i;
706         head=tail=1; que[tail++]=(Queue){i-2,sum[i-1]-f[cur][i-1]};
707         for (int j=i+1;j<=n;j++)
708         {
709             Queue u=(Queue){j-2,sum[j-1]-f[cur][j-1]};
710             while (head<tail-1 && que[tail-1]*que[tail-2]>u*que[tail-1]) tail--;
711             que[tail++]=u;
712             while (head<tail-1 && calc(j,que[head].x+1)<calc(j,que[head+1].x+1)) head++;
713             f[cur^1][j]=calc(j,que[head].x+1); p[i][j]=que[head].x+1;
714             if (ans<f[cur^1][j]) ans=f[cur^1][j],xx=i,yy=j;
715         }
716         cur^=1;
717     }
718     
719     lld Ans=lld(a0);
720     for (;xx;yy=p[xx][yy],xx--) sta[++top]=yy; sta[++top]=yy;
721     for (int i=top;i>1;i--) Ans=(Ans+(sum[sta[i-1]]-sum[sta[i]]))/(sta[i-1]-sta[i]+1);
722     
723     std::string s=Ans.to_string(P+2);
724     std::cout<<s<<std::endl;
725     return 0;
726 }
View Code

 

posted @ 2018-07-03 14:29  Blue233333  阅读(283)  评论(0编辑  收藏  举报