hnoi2012 (bzoj2727~2734)

题目就不贴了,自己看吧。


这套题每道题如果会做的话写代码的过程真是轻松加愉快……湖南人出的题似乎都是这样……真有水平……


hnoi2012 day1:

bzoj2727 双十字 cross

要求我们统计双十字的个数

r*c<=10^6

所以我们可以扫一遍整个矩阵- -

因为竖线只有一条,所以以其为主线来考虑

首先我们可以线性处理出来每个点最多向左向右延伸多少

考虑一个点作为下端的情况有多少种,即是他以上有多少个“土”

那我们考虑以一个点为双十字下面那根横线,能形成多少个“土”

设这个为点最多向两边延伸长度为len,c[i]为它以上最多向两边延伸长度i的图形的个数

就是说这样的

(

 *

***


 *

 *

***

)

那么我们这一行长度为2~len

形成“土”的个数显然为(len-1)*c[1]+((len-1)+(len-2))*c[2]..+((len-1)+..+1)*c[len-1]+((len-1)+..+1)*(c[len]+..+c[maxlen]) (长度大于等于他的等价于比他短1的)

这个怎么算呢……

显然等价于len*(1*c[1]+2*c[2]+..(len-1)*c[len-1])-(1*c[1]+(1+2)*c[2]+(1+2+3)*c[3]+..+(1+..+(len-1))*c[len-1])+(1+..+(len-1))*(c[len]+..c[maxlen])

…………

开三个树状数组好了

虽然推导有点麻烦,但是写还是很好写的,因为只用写个树状数组


bzoj2728 与非 nand

= =比较烦的一道题

首先玩下nand

发现这个东西好神啊,可以模拟出来not、and、or、xor,有了这些常用运算,

然后我们把n个数写成二进制数

比如

(7)2=111

(5)2=101

(3)2=011


然后我们竖着看……如果有两列完全相同,那么我们是没法让造出来的数这两位不同的

为什么呢……显而易见吧……位运算跟别的位没有关系两位等价就不能不相同

实际上没有两位必须等价的话,我们可以nand出任意数

也很好证明

既然有or运算,那么我们只要做出来各种只有一位为1,其他都为0的即可造出所有数

那么我们让某位为1,其他位为该如何操作……

可以对这n个数中这一位为0进行取反,然后把n个数and起来,如果其他位列跟着一列不同,其他位必然为0……因为这位全是1

知道了这个结论接下来就十分好做了,数位dp就行了


bzoj2729 排队 queue

组合数学题,比较简单吧

因为男生没有限制,所以先排男生,用n!种排列方式

这样就有n+1个缝隙可供我们放老师和女生

可以分情况讨论

两个老师在同一个缝隙中,这时候两个老师中间必须有一个女生,情况有A(n+1,1)*m*A(n+2,m-1)种

两个老师不在同一个缝隙中,情况有A(n+1,2)*A(n+3,m)种

所以答案为n!(A(n+1,1)*m*A(n+2,m-1)+A(n+1,2)*A(n+3,m))

显然答案会爆任意数据类型……需要高精度


bzoj2730 矿场搭建 mining

思考一下可以发现,只有割点崩塌才会出现问题,不然不影响图的连通性……

所以把割点全部删除以后,图会分成几个联通块

显然的,只跟一个割点相连的联通块内必须放一个出口,所以答案就是只跟一个割点相连的联通块大小之积

…………

实际上还有一种特殊情况……

图没割点……

放一个出口就够了?

显然不够,出口塌了怎么办……所以任意选两个点做为出口都行


bzoj2731 三角形覆盖问题 triangle

这题实际上有稳定算法……

不过感觉比较麻烦就写了个跑得比较快的爆搞……实际上应该比稳定算法还快,数据似乎是随机的

显然可以一行一行求面积

一行的面积=(上一行计算新出现的三角形的覆盖长度+这一行不算新出现的三角形的覆盖长度)/2

…………一行一行扫好了

怎么求被覆盖的长度呢……

数轴比较短啊……记录每一段被覆盖了多少次很容易求出来啊……

每一段覆盖了多少次怎么知道……?加三角形的时候爆搞啊……升高一行减掉当前的三角形小时的部分啊

这样据说可以过80分

但是说了这个比稳定算法还快,所以加个优化……

暴力判下新加入的三角形是不是在当前某个三角形内部,在的话不加

…………

ac了…………


bzoj2732 射箭 archery

因为抛物线过原点可得抛物线方程y=ax^2+bx

对于某个靶子x,y1,y2

可得y1<=ax^2+bx<=y2

把ab当成x、y就是两个半平面

可以求半平面交了

一条一条加入半平面如果半平面为空就结束

似乎又是随机数据……n^2做即可

还有个什么随机增量算法……期望O(n)……不懂

这个牵扯到大量实数运算,eps需要设到1e-16


bzoj2733 永无乡neverland

简化一下题意

有两种操作

1、求一个集合的第k大的数是哪个

2、将两个集合并起来

很容易想到平衡树……但是如何合并两颗平衡树

这用到了平衡树的启发式合并

启发式合并……听起来很高端……实际上就是合并两棵树的时候把小的树里的元素一个一个塞进大的树

…………

显然,复杂度最坏nlog^2n


bzoj2734 集合选数 set

首先考虑一下互相的约束

可以发现,只有2^i*3^j*x会互相制约

那么1~n的数就被划分成了几个互相独立的系统

方案数就是各系统方案数之积

问题转化成了求一个系统的方案数

观察一下x=1的情况

9 18  36

3   6   12

1   2     4

可以按2^i次方划分成一列一列

显然,一行不会超过11个元素(3^11>10^5)

一个数选择的话,相邻的四个数都不能选

显然可以状态压缩动态规划

复杂度不太好算……但是能很快通过


我最初的想法是把这个矩阵斜着看……发现状态很多,而且转移很慢

实际上这道题在matrix67的博客上有讲过


program bzoj2727;
const
    maxn=1000000009;
var
    z,ans,tot,now,x,y,r,c,n,i,j,k,o:longint;
    s,tree:array [0..2,0..1200001] of longint;
    dl,w:array [0..1200001] of longint;
    map:array [0..1200001] of boolean;    

function lowbit (x:longint):longint;inline;
begin
    exit(x xor (x and (x-1)));
end;

procedure insert (p,o,x:longint);inline;
begin
    if x=0 then exit;
    p:=int64(p)*s[o,x] mod maxn;
    while x<=c do
        begin
            tree[o][x]:=(tree[o][x]+p) mod maxn;
            x:=x+lowbit(x);
        end;
end;

function find (o,x:longint):longint;inline;
var
    ans:longint;
begin
    ans:=0;
    while x>0 do
        begin
            ans:=(ans+tree[o][x]) mod maxn;
            x:=x-lowbit(x);
        end;
    exit(ans);
end;

begin
    read(r,c);
    read(n);
    for i:=1 to n do
        begin
            read(x,y);
            map[x*c-c+y]:=true;
        end;
    for i:=1 to r do
        begin
            now:=1;
            for j:=1 to c do
                if map[i*c-c+j] then
                    now:=j+1
                                        else
                    w[i*c-c+j]:=j-now;
            now:=c;
            for j:=c downto 1 do
                if map[i*c-c+j] then
                    now:=j-1
                                    else
                if now-j1 then
                            begin
                                k:=int64(w[dl[tot]])*find(1,w[dl[tot]]-1) mod maxn;
                                k:=(k-find(2,w[dl[tot]]-1)) mod maxn;
                                k:=(k+(find(0,c)-find(0,w[dl[tot]]-1))*(int64(w[dl[tot]]-1)*w[dl[tot]]) div 2 mod maxn) mod maxn;
                                z:=(z+k) mod maxn;
                            end;
                        if (tot>=3)and(w[dl[tot-1]]>0) then
                            for k:=0 to 2 do
                                insert(tot-2,k,w[dl[tot-1]]);
                    end;
        end;
    ans:=(ans+maxn) mod maxn;
    writeln(ans);
end.

program bzoj2728;
type
    st=array [0..1001] of boolean;
const
    one:int64=1;
var
    n,i,j,k:longint;
    l,r:int64;
    a:array [0..1001] of int64;
    eve:array [0..60] of st;
    count,dl,fa:array [0..60] of longint;

procedure swap (var a,b:longint);inline;
begin
    if a=b then exit;
    a:=a xor b;
    b:=a xor b;
    a:=a xor b;
end;

function over (a,b:st):boolean;inline;
var
    i:longint;
begin
    for i:=1 to n do
        if a[i]>b[i] then exit(true)
                        else
        if a[i]0 then
                if fa[i]=0 then 
                    ans:=ans+(one shl (count[i]-1))
                                else
                if n and (one shl fa[i])=0 then 
                    ans:=ans+(one shl count[i]);
            if fa[i]<>0 then 
                if (n and (one shl i)) shr i <> (n and (one shl fa[i])) shr fa[i] then
                    break;
        end;
    if (fa[i]=0)or((fa[i]<>0)and(n and (one shl i) shr i=n and (one shl fa[i]) shr fa[i])) then inc(ans);
    exit(ans);
end;

begin
    read(n,k,l,r);
    if l>(one shl k)-1 then 
        begin
            writeln(0);
            halt;
        end;
    if r>=(one shl k) then 
        r:=(one shl k)-1;
    for i:=1 to n do
        read(a[i]);
    for i:=0 to k - 1 do
        for j:=1 to n do
            eve[i][j]:=(a[j] and (one shl i))=0;
    for i:=1 to k do
        dl[i]:=i-1;
    for i:=1 to k do 
        for j:=i+1 to k do
            if  (over(eve[dl[i]],eve[dl[j]]))or
            ((not over(eve[dl[i]],eve[dl[j]]))and(not over(eve[dl[j]],eve[dl[i]]))and(dl[i]

program bzoj2729;
type
    gj=array [0..100001] of longint;
var
	n,m,i,j,k:longint;
    ans,temp:gj;

procedure mul (var a:gj; b:longint);inline;
var
    i:longint;
begin
    for i:=a[0] downto 1 do
        a[i]:=a[i]*b;
    i:=1;
    while (i<=a[0])or(a[i]>0) do
        begin
            a[i+1]:=a[i+1]+a[i] div 10;
            a[i]:=a[i] mod 10;
            inc(i);
        end;
    dec(i);
    a[0]:=i;
end;

procedure plus (var a,b:gj);inline;
var
    i,k:longint;
begin
    if a[0]>b[0] then k:=a[0]
                        else k:=b[0];
    for i:=1 to k do
        begin
            a[i]:=a[i]+b[i];
            a[i+1]:=a[i+1]+a[i] div 10;
            a[i]:=a[i] mod 10;
        end;
    if a[k+1]<>0 then inc(k);
    a[0]:=k;
end;

begin
    read(n,m);
    if (n=0)and(m=0) then 
        begin
            writeln(0);
            exit;
        end;
    temp[0]:=1;
    temp[1]:=1;
    mul(temp,n+1);
    mul(temp,2);
    mul(temp,m);
    for i:=n+2 downto n+2-m+2 do
        mul(temp,i);
    ans:=temp;
    fillchar(temp,sizeof(temp),0);
    temp[0]:=1;
    temp[1]:=1;
    mul(temp,n+1);
    mul(temp,n);
    for i:=n+3 downto n+3-m+1 do
        mul(temp,i);
    plus(ans,temp);
    for i:=2 to n do
        mul(ans,i);
    for i:=ans[0] downto 1 do
        write(ans[i]);
    writeln;
end.

program bzoj2730;
var
    ans:int64;
    all,w,tot,s,t,max,n,i,j,k:longint;
    dd,count,belong,dfn,low,root,fa:array [0..201] of longint;
    yes,divide:array [0..201] of boolean;
    point,next:array [0..1001] of longint;

procedure connect (u,v:longint);inline;
begin
    inc(tot);
    point[tot]:=v;
    next[tot]:=root[u];
    root[u]:=tot;
end;

procedure dfs (now:longint);
var
    i,k:longint;
begin
    inc(tot);
    dfn[now]:=tot;
    low[now]:=tot;
    i:=root[now];
    k:=0;
    while i<>0 do
        begin
            if point[i]<>fa[now] then
                if dfn[point[i]]=0 then 
                    begin
                        inc(k);
                        fa[point[i]]:=now;
                        dfs(point[i]);
                        if low[point[i]]1)and(low[point[i]]>=dfn[now]) then divide[now]:=true;
                        if (now=1)and(k>1) then divide[now]:=true;
                    end
                                        else
                    if dfn[point[i]]0 do
        begin
            if (not yes[point[i]])and(not divide[point[i]]) then 
                search(point[i]);
            i:=next[i];
        end;
end;

begin
    w:=0;
    repeat
        read(n);
        if n=0 then break;
        max:=0;
        fillchar(root,sizeof(root),0);
        for i:=1 to n do
            begin
                read(s,t);
                if t>max then max:=t;
                connect(s,t);
                connect(t,s);
            end;
        tot:=0;
        fillchar(divide,sizeof(divide),false);
        fillchar(dfn,sizeof(dfn),0);
        dfs(1);
        fillchar(yes,sizeof(yes),false);
        fillchar(count,sizeof(count),0);
        tot:=0;
        for i:=1 to max do
            if (not yes[i])and(not divide[i]) then
                begin
                    inc(tot);
                    search(i);
                end;
        inc(w);
        write('Case ',w,': ');
        if tot=1 then
            begin
                writeln(2,' ',max*(max-1) div 2);
                continue;
            end;
        fillchar(dd,sizeof(dd),0);
        for i:=1 to max do 
            if divide[i] then
                begin
                    fillchar(yes,sizeof(yes),false);
                    k:=root[i];
                    while k<>0 do
                        begin
                            if (not divide[point[k]])and(not yes[belong[point[k]]]) then 
                                begin
                                    yes[belong[point[k]]]:=true;
                                    inc(dd[belong[point[k]]]);
                                end;
                            k:=next[k];
                        end;
                end;
        all:=0;
        ans:=1;
        for i:=1 to tot do
            if dd[i]=1 then
                begin
                    inc(all);
                    ans:=ans*count[i];
                end;
        writeln(all,' ',ans);
    until false;
end.

program bzoj2731;
var
    ans:double;
    max,h,len,now,tot,n,i,j,k:longint;
    dl,next,last,x,y,d:array [0..10001] of longint;
    count:array [0..2000001] of longint;
    ok:boolean;

procedure swap (var a,b:longint);inline;
begin
    if a=b then exit;
    a:=a xor b;
    b:=a xor b;
    a:=a xor b;
end;

procedure qsort (s,e:longint);
var
    i,j,k:longint;
begin
    if s>=e then exit;
    i:=s;
    j:=e;
    k:=y[dl[(s+e) div 2]];
    while i<=j do
        begin
            while y[dl[i]]k do dec(j);
            if i>j then break;
            swap(dl[i],dl[j]);
            inc(i);
            dec(j);
        end;
    qsort(s,j);
    qsort(i,e);
end;

begin
    read(n);
    for i:=1 to n do
        begin
            read(x[i],y[i],d[i]);
            dl[i]:=i;
            if y[i]+d[i]>max then max:=y[i]+d[i];
        end;
    qsort(1,n);
    next[0]:=10001;
    last[10001]:=0;
    len:=0;
    h:=y[dl[1]];
    i:=1;
    while h<=max do
        begin
            now:=len;
            k:=next[0];
            while k<>10001 do
                begin
                    dec(count[x[k]+d[k]-(h-y[k])]);
                    if count[x[k]+d[k]-(h-y[k])]=0 then dec(now);
                    if h=y[k]+d[k] then
                        begin
                            next[last[k]]:=next[k];
                            last[next[k]]:=last[k];
                        end;
                    k:=next[k];
                end;
            ans:=ans+(now+len)/2;
            len:=now;
            while (i<=n)and(y[dl[i]]=h) do
                begin
                    ok:=true;
                    k:=next[0];
	                while k<>10001 do
                        begin
                            if (x[k]<=x[dl[i]])and(x[dl[i]]+d[dl[i]]<=x[k]+d[k]-(h-y[k])) then
                                begin
                                    ok:=false;
                                    break;
                                end;
                            k:=next[k];
                        end;
                    if d[dl[i]]=0 then ok:=false;
                    if ok then
                        begin
                            last[next[0]]:=dl[i];
                            next[dl[i]]:=next[0];
                            last[dl[i]]:=0;
                            next[0]:=dl[i];
                            for j:=x[dl[i]] to x[dl[i]]+d[dl[i]]-1 do
                                begin
                                    if count[j]=0 then inc(len);
                                    inc(count[j]);
                                end;
                        end;
                    inc(i);
                end;
            inc(h);
        end;
    writeln(ans:0:1);
end.

program bzoj2732;
const
    eps:extended=1e-16;
    inf:extended=9999999999;
type
    point=
            record
                x,y:extended;
            end;
var
    ans,o,n,i,j,k:longint;
    tot:array [0..1] of longint;
    x,y1,y2:array [0..100001] of longint;
    dl:array [0..1,0..100001] of point;

function get (x1,y1,x2,y2,k2,b2:extended):point;
var
    k1,b1:extended;
    ans:point;
begin
    if abs(x1-x2)<=eps then 
        begin
            ans.x:=x1;
            ans.y:=x1*k2+b2;
            exit(ans);
        end;
    k1:=(y1-y2)/(x1-x2);
    b1:=y1-x1*k1;
    ans.x:=(b1-b2)/(k2-k1);
    ans.y:=ans.x*k1+b1; 
    exit(ans);
end;

procedure meet (k,b:extended;p:longint);
var
    i,j:longint;
begin
    o:=1-o;
    tot[o]:=0;
    for i:=1 to tot[1-o] do
        begin
            if dl[1-o,i].y*p>=(dl[1-o,i].x*k+b)*p then 
                begin
                    inc(tot[o]);
                    dl[o,tot[o]]:=dl[1-o,i];
                end;
            j:=i mod tot[1-o] + 1;
            if (dl[1-o,i].y*p>(dl[1-o,i].x*k+b)*p)xor(dl[1-o,j].y*p>(dl[1-o,j].x*k+b)*p) then
                begin
                    inc(tot[o]);
                    dl[o,tot[o]]:=get(dl[1-o,i].x,dl[1-o,i].y,dl[1-o,j].x,dl[1-o,j].y,k,b);
                end;
        end;
end;

begin
    read(n);
    for i:=1 to n do
        read(x[i],y1[i],y2[i]);
    tot[o]:=4;
    dl[o,1].x:=-inf;
    dl[o,1].y:=0;
    dl[o,2].x:=-inf;
    dl[o,2].y:=inf;
    dl[o,3].x:=inf;
    dl[o,3].y:=inf;
    dl[o,4].x:=inf;
    dl[o,4].y:=0;
    for i:=1 to n do
        begin
            ans:=i;
            meet(-x[i],y1[i]/x[i],1);
            meet(-x[i],y2[i]/x[i],-1);
            if tot[o]<=2 then
                begin
                    ans:=i-1;
                    break;
                end;
        end;
    writeln(ans);
end.

program bzoj2733;
var
    o,u,v,n,m,q,i,j,k:longint;
    ch:char;
    fa,tot,left,right,heap:array [0..200001] of longint;
    a,father,sum:array [0..100001] of longint;

procedure swap (var a,b:longint);inline;
begin
    if a=b then exit;
    a:=a xor b;
    b:=a xor b;
    a:=a xor b;
end;

function root (now:longint):longint;
begin
    if father[now]=0 then exit(now);
    father[now]:=root(father[now]);
    exit(father[now]);
end;

procedure rotate (son:longint);inline;
var
    mot:longint;
begin
    mot:=fa[son];
    fa[son]:=fa[mot];
    if fa[mot]<>0 then 
        if left[fa[mot]]=mot then 
            left[fa[mot]]:=son
                                        else
            right[fa[mot]]:=son;
    fa[mot]:=son;
    if left[mot]=son then 
        begin
            tot[mot]:=tot[mot]-tot[son]-1;
            left[mot]:=right[son];
            if right[son]<>0 then fa[right[son]]:=mot;
            right[son]:=mot;
        end
                            else
        begin
            tot[son]:=tot[son]+tot[mot]+1;
            right[mot]:=left[son];
            if left[son]<>0 then fa[left[son]]:=mot;
            left[son]:=mot;
        end;
end;

procedure insert (now:longint);inline;
var
    i:longint;
begin
    heap[now]:=random(maxlongint);
    i:=o;
    repeat
        if a[i]>a[now] then
            if left[i]=0 then 
                begin
                    left[i]:=now;
                    break;
                end
                            else
                i:=left[i]
                            else
            if right[i]=0 then
                begin
                    right[i]:=now;
                    break;
                end
                                else
                i:=right[i]
    until false;
    tot[now]:=0;
    fa[now]:=i;
    left[now]:=0;
    right[now]:=0;
    i:=now;
    repeat
        if left[fa[i]]=i then inc(tot[fa[i]]);
        i:=fa[i];
    until fa[i]=0;
    while heap[now]>heap[fa[now]] do rotate(now);
    if fa[now]=0 then o:=now;
end;

procedure dfs (now:longint);
begin
    if left[now]<>0 then 
        begin
            fa[left[now]]:=0;
            dfs(left[now]);
            left[now]:=0;
        end;
    if right[now]<>0 then 
        begin
            fa[right[now]]:=0;
            dfs(right[now]);
            right[now]:=0;
        end;
    insert(now);
end;

procedure link (u,v:longint);
var
    i:longint;
begin
    u:=root(u);
    v:=root(v);
    if u=v then exit;
    if sum[u]>sum[v] then swap(u,v);
    father[u]:=v;
    sum[v]:=sum[u]+sum[v];
    while fa[u]<>0 do u:=fa[u];
    while fa[v]<>0 do v:=fa[v];
    o:=v;
    dfs(u);
end;

function find (now,k:longint):longint;inline;
begin
    repeat
        if tot[now]+1=k then exit(now)
                                else
        if tot[now]+10 do u:=fa[u];
                    writeln(find(u,v));
                end
                            else
                link(u,v);
        end;
end.

program bzoj2734;
const
    modu=1000000001;
var
    o,ans,n,i,j,k:longint;
    thr,two:array [0..17] of longint;
    tot:array [0..1] of longint;
    dl,f:array [0..1,0..2048] of longint;
    yes:array [0..100001] of boolean;

function calc (w:longint):longint;inline;
var
    ans,i,j,k:longint;

procedure dfs (x,y,fob,stu,plus:longint);
var
    i:longint;
begin
    if w*two[x]*thr[y]>n then 
        begin
            if f[o][stu]=0 then
                begin
                    inc(tot[o]);
                    dl[o][tot[o]]:=stu;
                end;
            f[o][stu]:=(f[o][stu]+plus) mod modu;
            exit;
        end;
    dfs(x,y+1,fob,stu,plus);
    if fob and two[y] = 0 then
        dfs(x,y+2,fob,stu or two[y],plus);
end;

begin
    o:=0;
    tot[o]:=1;
    dl[o][1]:=0;
    f[o][0]:=1;
    i:=-1;
    while tot[o]>0 do
        begin
            inc(i);
            for j:=0 to 11 do
                if int64(w)*two[i]*thr[j]>n then break
                                                        else
                    yes[int64(w)*two[i]*thr[j]]:=true;
            o:=1-o;
            fillchar(f[o],sizeof(f[o]),0);
            tot[o]:=0;
            for j:=1 to tot[1-o] do
                if w*two[i]<=n then 
                    dfs(i,0,dl[1-o,j],0,f[1-o,dl[1-o,j]]);
        end;
    o:=1-o;
    ans:=0;
    for i:=1 to tot[o] do
        ans:=(ans+f[o][dl[o,i]]) mod modu;
    exit(ans);
end;

begin
    two[0]:=1;
    for i:=1 to 18 do
        two[i]:=two[i-1]*2;
    thr[0]:=1;
    for i:=1 to 12 do
        thr[i]:=thr[i-1]*3;
    ans:=1;
    read(n);
    for i:=1 to n do
        if not yes[i] then
            ans:=int64(ans)*calc(i) mod modu;
    writeln(ans);
end.



你可能感兴趣的:(hnoi2012 (bzoj2727~2734))