题目就不贴了,自己看吧。
这套题每道题如果会做的话写代码的过程真是轻松加愉快……湖南人出的题似乎都是这样……真有水平……
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.