Editorial for Phân tập


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

Code mẫu của flashmt

const fi='';
      fo='';
      maxs=65536;
      max=16000000;
type ar=array[0..maxs] of longint;
var n,m,m1,m2,i,j,k,sum,t,num,q,rem,temp,re:longint; dem:int64;
    a:array[0..31] of longint;
    b:array[0..15] of longint;
    p:array[0..16] of longint;
    f,g,sl:ar;
    tr:array[0..max] of longint;
    npos:longint;

procedure rf;
var i:longint;
begin
     assign(input,fi);
     reset(input);
     p[0]:=1;
     for i:=1 to 16 do p[i]:=p[i-1] shl 1;
     readln(n);
     m:=n div 2-1;
     m1:=p[m+1]-1;
     sum:=0;
     for i:=0 to m do
     begin
          read(a[i]);
          sum:=sum+a[i];
     end;
     m:=n-n div 2-1;
     for i:=0 to m do
     begin
          read(b[i]);
          sum:=sum+b[i];
     end;
     m2:=p[m+1]-1;
     close(input);
end;

procedure wf;
begin
     assign(output,fo);
     rewrite(output);
     write(re,' ',dem);
     close(output);
end;

procedure sort(l,r:longint);
var x,y,i,j:longint;
begin
     i:=l; j:=r; x:=f[(i+j) div 2];
     repeat
           while f[i]<x do i:=i+1;
           while f[j]>x do j:=j-1;
           if i<=j then
           begin
                y:=f[i]; f[i]:=f[j]; f[j]:=y;
                i:=i+1; j:=j-1;
           end;
     until i>j;
     if i<r then sort(i,r);
     if l<j then sort(l,j);
end;

function bs(x:longint;var num:longint):longint;
var l,r,m,y,re,t,u,i:longint;
begin
     l:=1; r:=npos; num:=0; y:=-1; re:=maxlongint; bs:=re;
     while l<=r do
     begin
          m:=(l+r) shr 1;
          if f[m]=x then break;
          if f[m]<x then l:=m+1
          else r:=m-1;
     end;
     if rem=0 then
     begin
          for i:=m-1 to m+1 do
              if (i>0) and (i<=npos) and (abs(f[i]-x)<re) then
              begin
                   re:=abs(f[i]-x);
                   y:=f[i];
              end;
          if y<>-1 then
          begin
               bs:=re*2;
               t:=tr[y];
               num:=sl[t];
               if re<>0 then
               begin
                    if (2*x-y<0) or (2*x-y>max) then exit;
                    t:=tr[2*x-y];
                    if t>0 then num:=num+sl[t];
               end;
          end;
     end
     else
     begin
          for i:=m-2 to m+2 do
              if (i>0) and (i<=npos) then
              begin
                   if f[i]<=x then
                   begin
                        if x-f[i]<re then
                        begin
                             re:=abs(f[i]-x);
                             y:=f[i];
                        end;
                   end
                   else
                   begin
                        if f[i]-1-x<re then
                        begin
                             re:=f[i]-x-1;
                             y:=f[i];
                        end;
                   end;
              end;
          if y<>-1 then
          begin
               bs:=2*re+1;
               t:=tr[y];
               num:=num+sl[t];
               if (2*x+1-y<0) or (2*x-y+1>max) then exit;
               t:=tr[2*x+1-y];
               if t>0 then num:=num+sl[t];
          end;
     end;
end;

begin
     rf;
     for i:=1 to m1 do
     begin
          k:=i; j:=0;
          while k>0 do
          begin
               if k and 1=1 then f[i]:=f[i]+a[j];
               j:=j+1;
               k:=k shr 1;
          end;
     end;
     sort(0,m1);

     g:=f;
     npos:=1;
     fillchar(f,sizeof(f),0);
     f[1]:=0; tr[0]:=1; sl[1]:=1;
     for i:=1 to m1 do
         if g[i]=g[i-1] then inc(sl[npos])
         else
         begin
              inc(npos);
              f[npos]:=g[i];
              tr[g[i]]:=npos;
              sl[npos]:=1;
         end;

     re:=maxlongint-10; dem:=0; q:=sum div 2; rem:=sum mod 2;
     m2:=m2 shr 1;
     for i:=0 to m2 do
     begin
          k:=i; j:=0; temp:=0;
          while k>0 do
          begin
               if k and 1=1 then temp:=temp+b[j];
               j:=j+1;
               k:=k shr 1;
          end;
          t:=bs(q-temp,num);
          if t<re then
          begin
               re:=t;
               dem:=num;
          end
          else
          begin
               if t=re then dem:=dem+num;
          end;
     end;
     wf;
end.

Code mẫu của ladpro98

program LQDDIV;
uses    math;
const   maxn=33;
        fi='';
type    pair=record
        x,y:int64;
        end;
var     n,lim,d:longint;
        res,count,sum,m:int64;
        a:array[1..maxn] of longint;
        s:array[1..1 shl (maxn shr 1)] of int64;

procedure Enter;
var     inp:text;
        i:longint;
begin
        assign(inp,fi);reset(inp);
        readln(inp,n);
        for i:=1 to n do begin
                read(inp,a[i]);
                inc(a[i],a[i]);
                inc(sum,a[i]);
        end;
        close(inp);
        lim:=n div 2;
        m:=sum div 2;
        res:=high(int64);
end;

procedure findAbs(key:int64; var p:pair);
var     l,r,m:longint;
begin
        l:=1;r:=d;
        while abs(l-r)<>1 do begin
                m:=(l+r) shr 1;
                if s[m] = key then begin
                        p.x:=s[m];p.y:=s[m];
                        exit;
                end;
                if s[m] < key then l:=m
                else r:=m;
        end;
        if abs(s[l]-key)=abs(s[r]-key) then begin
                p.x:=s[l];p.y:=s[r];
                exit;
        end;
        if abs(s[l]-key)<abs(s[r]-key) then begin
                p.x:=s[l];p.y:=s[l];
        end
        else begin
                p.x:=s[r];p.y:=s[r];
        end;
end;

function findL(key:int64):longint;
var     l,r,m,k:longint;
begin
        l:=1;r:=d;
        while l<=r do begin
                m:=(l+r) shr 1;
                if s[m]>=key then begin
                        k:=m;
                        r:=m-1;
                end
                else    l:=m+1;
        end;
        exit(k);
end;

function findR(key:int64):longint;
var     l,r,m,k:longint;
begin
        l:=1;r:=d;
        while l<=r do begin
                m:=(l+r) shr 1;
                if s[m]<=key then begin
                        k:=m;
                        l:=m+1;
                end
                else    r:=m-1;
        end;
        exit(k);
end;

procedure update(k:int64);
var     l,r:longint;
        p:int64;
        t:pair;
begin
        findAbs(m-k,t);
        p:=2*(t.x+k)-sum;
        if abs(p)<res then begin
                res:=abs(p);
                l:=findL(t.x);
                r:=findR(t.y);
                count:=r-l+1;
        end
        else
        if abs(p) = res then begin
                l:=findL(t.x);
                r:=findR(t.y);
                inc(count,r-l+1);
        end;
end;

procedure Gen(i:longint; k:int64);
begin
        if i>lim then begin
                inc(d);
                s[d]:=k;
                exit;
        end;
        Gen(i+1,k);
        Gen(i+1,k+a[i]);
end;

procedure Back(i:longint; k:int64);
begin
        if i>n then begin
                update(k);
                exit;
        end;
        back(i+1,k);
        back(i+1,k+a[i]);
end;

procedure Sort(l,r:longint);
var     i,j:longint;
        p,t:int64;
begin
        if l>=r then exit;
        i:=l;j:=r;
        p:=s[random(r-l+1)+l];
        repeat
                while s[i]<p do inc(i);
                while s[j]>p do dec(j);
                if i<=j then begin
                        if i<j then begin
                                t:=s[i];
                                s[i]:=s[j];
                                s[j]:=t;
                        end;
                        inc(i);dec(j);
                end;
        until i>j;
        Sort(l,j);sort(i,r);
end;

begin
        Enter;
        Gen(1,0);
        Sort(1,d);
        Back(lim+1,0);
        write(res div 2,' ',count div 2);
end.

Code mẫu của RR

//Written by RR
{$R+,Q+}
{$Mode objfpc}
{$inline on}
uses math;
const
  FINP          =       '';
  FOUT          =       '';
  MAXN          =       33;
  MAXL          =       100111;
  sign          :       array[0..1] of longint=(-1,1);

var
  f1,f2         :       text;
  n,res,sum     :       longint;
  a             :       array[1..MAXN] of longint;
  x,e           :       array[0..1,1..MAXL] of longint;
  sl            :       array[0..1] of longint;

procedure openF;
    begin
      assign(f1,FINP); reset(f1);
      assign(f2,FOUT); rewrite(f2);
    end;

procedure closeF;
    begin
      close(f1);
      close(f2);
    end;

procedure sort(u,l,r:longint);
    var
      i,j,mid,tmp:longint;
    begin
      i:=l; j:=r; mid:=x[u,l+random(r-l+1)];
      repeat
        while x[u,i]<mid do inc(i);
        while x[u,j]>mid do dec(j);
        if i<=j then
          begin
            tmp:=x[u,i];
            x[u,i]:=x[u,j];
            x[u,j]:=tmp;
            inc(i); dec(j);
          end;
      until i>j;
      if i<r then sort(u,i,r);
      if l<j then sort(u,l,j);
    end;

procedure duyet(i,gh,k:longint);
    var
      j:longint;
    begin
      for j:=0 to 1 do
        begin
          sum:=sum+sign[j]*a[i];
          if i<gh then duyet(i+1,gh,k)
          else
            begin
              inc(sl[k]);
              x[k,sl[k]]:=sum;
            end;
          sum:=sum-sign[j]*a[i];
        end;
    end;

procedure solve;
    var
      i,j,tmp,res,count:longint;
    begin
      sum:=0;
      duyet(1,n>>1,0);
      sort(0,1,sl[0]);

      sum:=0;
      duyet(n>>1+1,n,1);
      sort(1,1,sl[1]);

      e[0,1]:=1; tmp:=1;
      for i:=2 to sl[0] do
        if x[0,i]>x[0,tmp] then
          begin
            inc(tmp);
            x[0,tmp]:=x[0,i];
            e[0,tmp]:=1;
          end
        else inc(e[0,tmp]);
      sl[0]:=tmp;

      e[1,1]:=1; tmp:=1;
      for i:=2 to sl[1] do
        if x[1,i]>x[1,tmp] then
          begin
            inc(tmp);
            x[1,tmp]:=x[1,i];
            e[1,tmp]:=1;
          end
        else inc(e[1,tmp]);
      sl[1]:=tmp;

      res:=high(longint); count:=0;
      j:=sl[1];
      for i:=1 to sl[0] do
        begin
          while (j>1) and (abs(x[1,j-1]+x[0,i])<abs(x[1,j]+x[0,i])) do dec(j);
          tmp:=abs(x[1,j]+x[0,i]);
          if tmp<res then
            begin
              res:=tmp;
              count:=e[0,i]*e[1,j];
            end
          else if tmp=res then inc(count,e[0,i]*e[1,j]);

          if j>1 then
            begin
              tmp:=abs(x[1,j-1]+x[0,i]);
              if tmp<res then
                begin
                  res:=tmp;
                  count:=e[0,i]*e[1,j-1];
                end
              else if tmp=res then inc(count,e[0,i]*e[1,j-1]);
            end;
        end;
      writeln(f2,res,' ',count div 2);
    end;

procedure inp;
    var
      i:longint;
    begin
      read(f1,n);
      for i:=1 to n do
        read(f1,a[i]);
    end;

begin
  openF;
  inp;
  solve;
  closeF;
end.

Code mẫu của hieult

#include <cstdio>
//#include <conio.h>
typedef long long ll;

void Quicksort(ll A[],ll lower,ll upper)
{
        ll x = A[(lower + upper) / 2];
        ll i = lower;
        ll j = upper;
        do{
                while(A[i] < x)
                        i ++;
                while (A[j] > x)
                        j --;
                if (i <= j)
                {
                     ll tg=A[i];
                     A[i]=A[j];
                     A[j]=tg;   
                        i ++;
                        j --;
                }
        }while(i <= j);
        if (j > lower)
                Quicksort(A, lower, j);
        if (i < upper)
                Quicksort(A, i, upper);
}  

    ll n,mu2[20],t,so,vitri;
    ll a[35],b[100000],f[100000],d[100000],tong=0,tt,max,tim,tongtim,gan;

int main()
{
    //freopen("LQDDIV1.in","r",stdin);
    scanf("%lld",&n);
    for(int i = 1;i<=n;i++) { scanf("%lld",&a[i]); tong+=a[i];}
    ll m = n/2; ll k = n-m;
    mu2[0] = 1; for(int i = 1;i<=20;i++) mu2[i] = mu2[i-1]<<1;
    for(int i = 0;i<mu2[m];i++)
    {
         gan = i; tt = 0;
         for(int j = 1;j<=m;j++){ if(gan%2==1) tt+= a[j]; gan/=2;}
         b[i+1] = tt;
    }
    //printf("%lld\n",mu2[m]);
    Quicksort(b,1,mu2[m]);
    //for(int i = 1;i<=10;i++) printf("%lld ",b[i]);
    t = 0;
    for(int i = 1;i<=mu2[m];i++)
    {
        if(i==1)
        {
             f[++t] = b[i];
             d[t] = 1;;
        }
        else
        {
            if(b[i]==b[i-1])
                 d[t]++;
            else
            {
                f[++t] = b[i];
                d[t] = 1;
            }
        }
    }
   //printf("%lld\n",tong);
    max = 0;
    for(int i = 0;i<mu2[k];i++)
    {
         gan = i; tt = 0;
         for(int j = 1;j<=k;j++){ if(gan%2==1) tt+= a[j+m]; gan/=2;}
         tim = tong/2 - tt;
         //if(i<16000&& i>=15980) printf("%lld\n",tim);
         //printf("%lld\n",tt);
         if(tim<0) continue;
         ll u = 1, v = t, r;
         while(v-u>1)
         {
            r = (u+v)/2;
            if(f[r]<=tim)
                u = r;
            else v = r;
            //if(v!=0)
         }
         //ll p1 = 45000 ,p2 = 100000;
         //if(tim == p1*p2 &&i<16000&& i>=15980) printf("%lld %lld\n",u,v);
         if(f[v]<=tim)
         {
              tongtim = f[v]+tt;
              vitri = v;
         }
         else
         {
              tongtim = f[u]+tt;
              vitri = u;
         }
         //if(tim == p1*p2 &&i<16000&& i>=15980) printf("***%lld***\n",tongtim);
         //if(tongtim%1000000000==0) printf("%lld %lld\n",u,v);
         if(tongtim > max) {max = tongtim; so = d[vitri];}
         else if(tongtim == max) {so+=d[vitri];}
    }
    //prllf("%d\n",tongtim);
    if(max*2==tong) so/=2;
    printf("%lld %lld",tong-2*max,so);
   //getch();
}

Code mẫu của ll931110

#include <iostream>
#include <cstdlib>
#define MAXV 65550
#define MAXN 33
using namespace std;

long long a[MAXV],b[MAXV],d[MAXV],kd[MAXV];
long long stmp,sum,u,delta;
int ta[MAXV],tb[MAXV],td[MAXV];
int na,nb,nd,n,tmpd,s[MAXN],k[MAXN],sup;

int compare_ints( const void* x, const void* y )
{  
     long long* arg1 = (long long*) x;
     long long* arg2 = (long long*) y;
     if( *arg1 < *arg2 ) return -1;
     else if( *arg1 == *arg2 ) return 0;
     else return 1;
}

void attempt(int i,int sup)
{
     for (int j = k[i - 1] + 1; j <= sup; j++)
     {
         k[i] = j;
         stmp += s[j];
         kd[++ nd] = stmp;

         if (j < sup) attempt(i + 1,sup);
         stmp -= s[j];
     }
}

void precalc()
{
     int i;

     nd = 0;
     stmp = 0;
     attempt(1,sup);

     qsort( kd, nd + 1, sizeof(long long), compare_ints);
     tmpd = 0;
     for (i = 0; i <= nd; i++) td[i] = 0;
     d[0] = 0;

     for (i = 0; i <= nd; i++)
       if (d[tmpd] == kd[i]) td[tmpd]++; 
       else
       {
           tmpd++;
           d[tmpd] = kd[i];
           td[tmpd] = 1;
       }
}


int main()
{
    int i,xa,xb;
    long long ncount;

    //freopen("lqddiv.inp","r",stdin);
    //freopen("lqddiv.out","w",stdout);

    scanf("%d", &n);
    sum = 0;
    for (i = 1; i <= n; i++) 
    {
        scanf("%d", &s[i]);
        sum += s[i];
    }

    sup = n/2;
    k[0] = 0;   
    precalc();
    na = tmpd;
    for (i = 0; i <= tmpd; i++) 
    {
        a[i] = d[i];
        ta[i] = td[i];
    }

    sup = n;
    k[0] = n/2;
    precalc();
    nb = tmpd;
    for (i = 0; i <= tmpd; i++) 
    {
        b[i] = d[i];
        tb[i] = td[i];
    }

    xa = 0;
    xb = nb;
    while (xb >= 0 && a[xa] + b[xb] > sum/2) xb--;      
    delta = a[xa] + b[xb];

    for (xa = 0; xa <= na; xa++)
    {
        while (xb >= 0 && a[xa] + b[xb] > sum/2) xb--;
        if (xb >= 0 && delta < a[xa] + b[xb]) delta = a[xa] + b[xb];
    }

    u = sum - 2 * delta;
    xa = 0;
    xb = nb;
    ncount = 0;

    while (xb >= 0 && a[xa] + b[xa] > delta) xb--;
    for (xa = 0; xa <= na; xa++)
    {
        while (xb >= 0 && a[xa] + b[xb] > delta) xb--;
        if (xb >= 0 && delta == a[xa] + b[xb]) ncount += ta[xa] * tb[xb];
    }

    if (u == 0) ncount = ncount/2;
    cout << u << " " << ncount;
}

Comments

Please read the guidelines before commenting.


There are no comments at the moment.