• NOIP2011解题报告Day2


    计算系数

            二项式定理。杨辉三角堆组数+快速幂。Noip的时候还没学二项式定理。。。

     1 const p=10007;maxk=1000;
     2 var  a,b,k,n,m:longint;
     3 function C(k,m:longint):longint;
     4          var f:array[0..maxk,0..maxk] of longint;
     5              i,j,n:longint;
     6          begin
     7          n:=k-m;
     8          if(n=0)or(m=0)then exit(1);
     9          for i:=0 to n do f[i][0]:=1;
    10          for j:=0 to m do f[0][j]:=1;
    11          for i:=1 to n do
    12            for j:=1 to m do
    13              f[i][j]:=(f[i-1][j]+f[i][j-1])mod p;
    14          exit(f[n][m]);
    15          end;
    16 function exp(a,b:longint):longint;
    17          var ans,temp:int64;
    18          begin
    19          ans:=1;temp:=a;
    20          while b<>0 do
    21            begin
    22            if((b and 1)=1)then ans:=(ans*temp)mod p;
    23            temp:=(temp*temp)mod p;
    24            b:=b shr 1;
    25            end;
    26          exit(ans);
    27          end;
    28 begin
    29   readln(a,b,k,n,m);
    30   if(n=0)and(m=0)
    31     then begin
    32          writeln(0);
    33          halt;
    34          end;
    35   a:=a mod p;b:=b mod p;
    36   writeln(C(k,m)*int64(exp(a,n))*exp(b,m) mod p);
    37 end.

    聪明的质检员

            考场上没看懂题目。。。

            发现Y是关于w的减函数,于是二分W,维护前缀和在O(n)的复杂度求出Y。总复杂度O(N log(max{wi}))

    PS:w离散化后二分复杂度应该是O(N log(N))时间没有快多少,可能出现在对数上影响不大.

      1 program qc;
      2 uses math;
      3 var n,m,i,low,high,mid,tot:longint;
      4     s,y:int64;
      5     l,r,w,v,sta:array[0..200000] of longint;
      6     count,sigmaV:array[0..200000] of int64;
      7     f:array[0..1000000] of boolean;
      8 function calc(mid:longint):int64;
      9          var i:longint;
     10          begin
     11          calc:=0;count[0]:=0;sigmaV[0]:=0;
     12          for i:=1 to n do
     13            begin
     14            count[i]:=count[i-1];
     15            sigmaV[i]:=sigmaV[i-1];
     16            if w[i]>mid
     17              then begin
     18                   inc(count[i]);
     19                   inc(sigmaV[i],v[i]);
     20                   end;
     21            end;
     22          for i:=1 to m do
     23            inc(calc,(count[r[i]]-count[l[i]-1])*
     24                     (sigmaV[r[i]]-sigmaV[l[i]-1]));
     25          end;
     26 begin
     27 high:=0;low:=maxlongint;
     28 readln(n,m,s);
     29 for i:=1 to n do
     30   begin
     31   readln(w[i],v[i]);
     32   low:=min(w[i],low);
     33   high:=max(w[i],high);
     34   f[w[i]]:=true;
     35   end;
     36 for i:=1 to m do
     37   readln(l[i],r[i]);
     38 //===lisuanhua===
     39 tot:=1;sta[tot]:=low-1;
     40 for i:=low to high do
     41   if f[i] then begin
     42                inc(tot);
     43                sta[tot]:=i;
     44                end;
     45 inc(tot);sta[tot]:=high+1;
     46 //===============
     47 low:=1;high:=tot;
     48 while low+1<high do
     49   begin
     50   mid:=(low+high)>>1;
     51   y:=calc(sta[mid]);
     52   if y>s then low:=mid
     53          else high:=mid;
     54   end;
     55 writeln(min(abs(s-calc(sta[low])),abs(s-calc(sta[high]))));
     56 end.
     57 //================================================
     58 program qc;
     59 uses math;
     60 var n,m,i,low,high,mid:longint;
     61     s,y:int64;
     62     l,r,w,v:array[0..200000] of longint;
     63     count,sigmaV:array[0..200000] of int64;
     64 function calc(mid:longint):int64;
     65          var i:longint;
     66          begin
     67          calc:=0;count[0]:=0;sigmaV[0]:=0;
     68          for i:=1 to n do
     69            begin
     70            count[i]:=count[i-1];
     71            sigmaV[i]:=sigmaV[i-1];
     72            if w[i]>mid
     73              then begin
     74                   inc(count[i]);
     75                   inc(sigmaV[i],v[i]);
     76                   end;
     77            end;
     78          for i:=1 to m do
     79            inc(calc,(count[r[i]]-count[l[i]-1])*
     80                     (sigmaV[r[i]]-sigmaV[l[i]-1]));
     81          end;
     82 begin
     83 high:=0;low:=maxlongint;
     84 readln(n,m,s);
     85 for i:=1 to n do
     86   begin
     87   readln(w[i],v[i]);
     88   low:=min(w[i],low);
     89   high:=max(w[i],high);
     90   end;
     91 for i:=1 to m do
     92   readln(l[i],r[i]);
     93 dec(low);inc(high);
     94 while low+1<high do
     95   begin
     96   mid:=(low+high)>>1;
     97   y:=calc(mid);
     98   if y>s then low:=mid
     99          else high:=mid;
    100   end;
    101 writeln(min(abs(s-calc(low)),abs(s-calc(high))));
    102 end.

    观光公交

    首先考虑k=0;如何计算出答案

            Leave[i]为最早允许离开i的时间 leave[i]=max{t[j]}(a[j]=i)

            可以再读入数据时处理出来leave[a[i]]:=max(T[i],leave[a[i]]);

            Get[i]为到达i站时间 Get[i]=max(get[i-1],leave[i-1])+D[i-1];

    枚举计算每个旅客的旅行时间

            Ans=sigma(i=1..m) (get[b[i]]-T[i])

            K=1时枚举给哪个D[i]减一即可

    满分做法:贪心

            发现给某个D[i]减一后会使后面连续的人等车的车站的乘客提前上车。直到一个车站leave[j]>get[j](车等人),人来的时间是不能跟改变的。所以提前了上车时间的旅客提前了的一分钟要在等人上浪费掉,所以旅行时间不会减小。也就是说令right[i]为i后面第一个满足车等人的站点。

            那么在i+1到right[i]这个区间内下车的人的旅行时间都会减小一。维护下车人数的前缀和S。

            给D[i]减一所减小的答案为S[right[i]]-S[right[i]]。每次找到最大的加速。找最大可以O(n)暴力,也可以维护堆O(log n)。减的时候有3种情况

            1.k很小全部用掉

    1.         2.D[i]很小全部减掉(必须保证每个D[i]>=0)
    2.         3.i+1..tright[i]中最小的Get[j]-Leave[j](把这个值减成负的会破坏现有的区间的关系,减成负的就变成车等人了)

    从这3个值中取最小值用掉

    然后O(n)重新计算i..right[i]-1的right值

    没写堆,在RQ上过了。Noip的数据很厚道。

     1 program bus;
     2 uses math;
     3 CONST
     4       maxn=1000;
     5       maxm=10000;
     6       maxk=1000000;
     7 var a,b,t:array[0..maxm] of longint;
     8     right,tot,s,cnt,GetIn,GetOff,get,leave,d:array[0..maxn+1] of longint;
     9     p,count,n,m,k,i,j,maxcnt,maxi,temp:longint;
    10     ans:int64;
    11 BEGIN
    12 read(n,m,k);
    13 for i:=1 to n-1 do read(D[i]);
    14 for i:=1 to m do
    15   begin
    16   read(t[i],a[i],b[i]);
    17   inc(GetOff[b[i]]);inc(GetIn[a[i]]);
    18   leave[a[i]]:=max(leave[a[i]],t[i]);
    19   end;
    20 for i:=2 to n do
    21   get[i]:=max(leave[i-1],get[i-1])+D[i-1];
    22 p:=1;
    23 for i:=1 to n do
    24   begin
    25   while((p<n)and(leave[p]<get[p]))or(p<=i)do inc(p);
    26   right[i]:=p;
    27   end;
    28 for i:=1 to n do
    29   s[i]:=s[i-1]+GetOff[i];
    30 while k>0 do
    31   begin
    32   maxcnt:=0;
    33   for i:=1 to n-1 do
    34     if (s[right[i]]-s[i]>maxcnt)and(D[i]>0)
    35       then begin
    36            maxcnt:=s[right[i]]-s[i];
    37            maxi:=i;
    38            end;
    39   if maxcnt=0
    40     then break
    41     else begin
    42          temp:=maxlongint;j:=maxi+1;
    43          while(j<n)and(leave[j]<get[j])do
    44            begin
    45            temp:=min(get[j]-leave[j],temp);
    46            inc(j);
    47            end;
    48          temp:=min(D[maxi],temp);temp:=min(k,temp);
    49          dec(k,temp);dec(D[maxi],temp);
    50          for j:=maxi+1 to right[i] do
    51            get[j]:=max(get[j-1],leave[j-1])+D[j-1];
    52          p:=maxi;count:=GetOff[maxi];
    53          for j:=maxi to right[i]-1 do
    54            begin
    55              while((p<n)and(leave[p]<get[p]))or(p<=j)do inc(p);
    56              if p>=right[j] then break;
    57              right[j]:=p;
    58            end;
    59          end;
    60   end;
    61 get[1]:=leave[1];get[n]:=max(get[n],leave[n]);
    62 for i:=1 to m do
    63   inc(ans,get[b[i]]-t[i]);
    64 writeln(ans);
    65 END.

     

  • 相关阅读:
    数据预处理--数据清洗
    数据运营(一)基本讲解概念及运营方式.
    基于skearn-learn 框架 的线性回归
    手写线性回归算法demo
    数据分析算法--线性回归算法讲解(2)
    数据分析算法--线性回归算法讲解
    数据监督与非监督
    numpy的常用函数以及常规操作
    数据分析--基础numpy(一)
    互斥锁,自旋锁,读写锁与原子操作
  • 原文地址:https://www.cnblogs.com/lijianlin1995/p/2637076.html
Copyright © 2020-2023  润新知