題目大意
按順時針或逆時針給定凸包上的n個點,隨機選取內部或邊上的整點,求兩點為正方形對角線的正方形面積的期望題解有
sum 個合法點(內部或邊上),那麼面積的期望為 an
s=12
∑sum
i=1∑
sumj
=1(x
i−xj
)2+(
yi−y
j)2n
⋅(n−
1)對於分子x和
y是同一
形式所以我們只看∑s
umi=
1∑su
mj=1
(xi−
xj)2
開啟括號後我們得到 ∑i
∑j(x
i2+x
j2)−
2⋅∑i
∑jxi
⋅xj=
2⋅su
m⋅∑i
xi2−
2⋅(∑
ixi)
2 這樣我們只需要求兩個字首和即可
剩下的問題就是統計所有點的個數和座標
如果暴力用掃瞄線去掃會t,但是我們發現對於一條掃瞄線所掃到的點
x 座標相同,所以用個數*座標值直接計入即可
一條掃瞄線同一時間會掃到凸包上的兩條邊,用交到的兩個點求一下個數即可
const
maxn=100005;
maxm=1000005;
var x,y:array[0..maxn]of int64;
wy,wx:array[0..maxm*2,1..2]of real; // k=(y1-y2)/(x1-x2); b=(x1y2-x2y1)/(x1-x2);
i,j,k:longint;
n,l,r,u,d,e,f,***,yyy:longint;
sum,summ,a,b,c:int64;
ans,x1,x2,y1,y2:real;
procedure
swap
(var a,b:real);
var c:real;
begin
c:=a; a:=b; b:=c;
end;
function
xx(a:real):int64;
begin
if trunc(a)then
exit(trunc(a)+1)
else
exit(trunc(a));
end;
function
g(a,b:real):int64;
var d,c:int64;
begin
d:=trunc(b);
c:=xx(a);
exit(d-c+1);
end;
begin
assign(input,'square.in'); assign(output,'square.out'); reset(input); rewrite(output);
readln(n);
readln(x[1],y[1]);
l:=x[1]; r:=x[1]; u:=y[1]; d:=y[1];
x[n+1]:=x[1]; y[n+1]:=y[1];
for i:=2
to n do
begin
readln(x[i],y[i]);
if x[i]then l:=x[i];
if x[i]>r then r:=x[i];
if y[i]then d:=y[i];
if y[i]>u then u:=y[i];
end;
for i:=0
to r-l do
begin
wx[i,1]:=maxm;
wx[i,2]:=maxm;
end;
for i:=0
to u-d do
begin
wy[i,1]:=maxm;
wy[i,2]:=maxm;
end;
***:=l; yyy:=d;
if ***<0
then inc(x[1],-***);
if yyy<0
then inc(y[1],-yyy);
l:=maxm; r:=-maxm; u:=-maxm; d:=maxm;
for i:=2
to n+1
dobegin
if ***<0
then inc(x[i],-***);
if yyy<0
then inc(y[i],-yyy);
if x[i]then l:=x[i];
if x[i]>r then r:=x[i];
if y[i]then d:=y[i];
if y[i]>u then u:=y[i];
if x[i]=x[i-1]
then
begin a:=0; b:=1; c:=x[i]; end
else
begin a:=y[i]-y[i-1]; b:=x[i]-x[i-1]; c:=x[i]*y[i-1]-x[i-1]*y[i]; end;
if x[i]1]
then
begin e:=x[i]; f:=x[i-1]; end
else
begin e:=x[i-1]; f:=x[i]; end;
for j:=e to f-1
doif wx[j,1]=maxm
then wx[j,1]:=(a*j+c)/b
else
if wx[j,2]=maxm
then wx[j,2]:=(a*j+c)/b;
if y[i]=y[i-1]
then
begin a:=1; b:=0; c:=-y[i]; end
else
begin a:=y[i]-y[i-1]; b:=x[i]-x[i-1]; c:=x[i]*y[i-1]-x[i-1]*y[i]; end;
if y[i]1]
then
begin e:=y[i]; f:=y[i-1]; end
else
begin e:=y[i-1]; f:=y[i]; end;
for j:=e to f-1
doif wy[j,1]=maxm
then wy[j,1]:=(j*b-c)/a
else
if wy[j,2]=maxm
then wy[j,2]:=(j*b-c)/a;
end;
sum:=0;
for i:=l to r do
begin
if wx[i,1]>wx[i,2] then swap(wx[i,1],wx[i,2]);
sum:=sum+g(wx[i,1],wx[i,2]);
end;
x1:=0; x2:=0;
for i:=l to r do
begin
x1:=x1+(g(wx[i,1],wx[i,2])*int64(i));
x2:=x2+(g(wx[i,1],wx[i,2])*int64(i)*int64(i));
end;
ans:=0;
ans:=(2*sum*x2-2*x1*x1)/2/sum/(sum-1);
y1:=0; y2:=0;
for i:=d to u do
begin
if wy[i,1]>wy[i,2] then swap(wy[i,1],wy[i,2]);
y1:=y1+(g(wy[i,1],wy[i,2])*int64(i));
y2:=y2+(g(wy[i,1],wy[i,2])*int64(i)*int64(i));
end;
ans:=ans+(2*sum*y2-2*y1*y1)/2/sum/(sum-1);
writeln(ans:0:10);
close(input); close(output);
end.
亦或問題
題目大意給定
n(n≤
50000)個
數,詢問
前m大的
aixo
raj的
和題解首先
因為每對
會出現2
次,所以
最後要除
以2,我
們考慮求
前2∗m
大的答案
亦或,還是最值
相關,我
們對所有
數建立t
rie樹
如果我們求出了第2∗
m 大的得數是多少,我們只要對每個數求出它亦或別的數後大於2∗
m 大的數的和計入答案即可
具體來說就是,