赞
踩
题目:luogu2119.
题目大意:给定一个长度为
m
m
m的序列
x
i
x_i
xi,要求求出满足
x
a
<
x
b
<
x
c
<
x
d
,
x
b
−
x
a
=
2
(
x
d
−
x
c
)
x_a<x_b<x_c<x_d,x_b-x_a=2(x_d-x_c)
xa<xb<xc<xd,xb−xa=2(xd−xc)且
x
b
−
x
a
<
x
c
−
x
b
3
x_b-x_a<\frac{x_c-x_b}{3}
xb−xa<3xc−xb的
a
,
b
,
c
,
d
a,b,c,d
a,b,c,d的数量.
1
≤
n
=
max
{
x
i
}
≤
1.5
∗
1
0
4
,
1
≤
m
≤
4
∗
1
0
4
1\leq n=\max \{x_i\}\leq 1.5*10^4,1\leq m\leq 4*10^4
1≤n=max{xi}≤1.5∗104,1≤m≤4∗104.
首先这道题可以直接用一个桶,先把所有数塞进这个桶里.
然后我们可以开始 O ( n 4 ) O(n^4) O(n4)枚举答案.
但我们发现 x d = x b − x a + 2 x c 2 x_d=\frac{x_b-x_a+2x_c}{2} xd=2xb−xa+2xc,所以我们可以省去以为的枚举,做到 O ( n 3 ) O(n^3) O(n3)枚举,实测在洛谷上能拿到85分.
到这一步优化的代码如下:
#include<bits/stdc++.h> using namespace std; #define Abigail inline void typedef long long LL; const int N=15000,M=40000; int n,m,x[M+9]; LL num[N+9][4],cnt[N+9]; Abigail into(){ scanf("%d%d",&n,&m); for (int i=1;i<=m;i++){ scanf("%d",&x[i]); cnt[x[i]]++; } } Abigail work(){ for (int a=1;a<=n;a++) for (int b=a+1;b<=n;b++) for (int c=b+1;c<=n;c++){ if (b-a&1||3*b-3*a>=c-b) continue; int d=b-a+c*2>>1; LL ans=cnt[a]*cnt[b]*cnt[c]*cnt[d]; num[a][0]+=ans;num[b][1]+=ans;num[c][2]+=ans;num[d][3]+=ans; } for (int i=1;i<=n;i++) for (int j=0;j<4;j++) num[i][j]/=cnt[i]?cnt[i]:1; } Abigail outo(){ for (int i=1;i<=m;i++){ for (int j=0;j<3;j++) printf("%lld ",num[x[i]][j]); printf("%lld\n",num[x[i]][3]); } } int main(){ into(); work(); outo(); return 0; }
接下来的优化需要将 x b − x a < x c − x b 3 x_b-x_a<\frac{x_c-x_b}{3} xb−xa<3xc−xb变式,改成 3 ( x b − x a ) < x c − x b 3(x_b-x_a)<x_c-x_b 3(xb−xa)<xc−xb.
然后我们设 t = x d − x c t=x_d-x_c t=xd−xc,那么 2 t = x b − x a , 6 t < x c − x b 2t=x_b-x_a,6t<x_c-x_b 2t=xb−xa,6t<xc−xb.
然后我们在设
6
t
+
k
=
x
c
−
x
b
6t+k=x_c-x_b
6t+k=xc−xb,那么就可以画一个图:
我们发现
x
d
−
x
a
=
9
t
+
k
x_d-x_a=9t+k
xd−xa=9t+k,由于所有数都是整数,所以
k
k
k的最小值为
1
1
1.
现在我们枚举 t t t和 x a x_a xa,我们就可以计算出 x b = x a + 2 t x_b=x_a+2t xb=xa+2t,然后 C C C的最小值为 x a + 2 t + 6 t + k m i n = x a + 8 t + 1 x_a+2t+6t+k_{min}=x_a+8t+1 xa+2t+6t+kmin=xa+8t+1, D D D的最小值为 x a + 8 t + 1 + t = x a + 9 t + 1 x_a+8t+1+t=x_a+9t+1 xa+8t+1+t=xa+9t+1.
我们发现若 t t t和 x a x_a xa确定了,那么我们就可以确定只有 k k k的问题了,我们发现 k k k取 [ 1 , n − 9 t ] [1,n-9t] [1,n−9t]内的任意一个数都是可以的,那我们就可以维护一个前缀和数组 v i s [ i ] [ t ] vis[i][t] vis[i][t]表示 c c c为 i i i, d d d为 i + t i+t i+t的时候有多少种.
由于这样会占用很大内存导致MLE,所以我们在推的时候处理,这样就可以确定 c c c和 d d d的数量了.但是要注意,由于我们要边处理边推,所以我们要逆推.
而 a a a和 b b b的确定和 c c c和 d d d很像,换成顺推就可以了.
而这样做的时间复杂度为 O ( n 2 ) O(n^2) O(n2),还是不能拿到满分.
接下来我们就进行一些细节的优化,我们发现 x a + 9 t + k < = n x_a+9t+k<=n xa+9t+k<=n,而 x a , k > = 1 x_a,k>=1 xa,k>=1,所以我们可以发现其实 t < = n − 2 9 t<=\frac{n-2}{9} t<=9n−2,所以 t t t只需要枚举到 n − 2 9 \frac{n-2}{9} 9n−2就可以了.但是这样写代码会有除法,比较慢,所以我们写成 9 t < = n − 2 9t<=n-2 9t<=n−2.
那么这个算法的时间复杂度就是 O ( n 2 9 ) O(\frac{n^2}{9}) O(9n2),可以过了,可能需要一定的常数优化(然而并没有什么可以优化的地方).
所以大致的算法流程如下:
1.枚举
t
=
1
→
n
2
9
t=1\rightarrow \frac{n^2}{9}
t=1→9n2.
2.枚举
D
=
n
→
2
+
9
t
D=n\rightarrow 2+9t
D=n→2+9t,可以推出
C
=
D
−
t
C=D-t
C=D−t,之后可以设
A
A
A为
A
A
A的最大值,
B
B
B为
B
B
B的最大值,得到
B
=
C
−
6
t
−
1
,
A
=
6
t
−
1
B=C-6t-1,A=6t-1
B=C−6t−1,A=6t−1.
3.在2的同时,记录一个
s
u
m
sum
sum初始为
0
0
0,表示当前
D
D
D时,
A
A
A和
B
B
B的情况有多少种.
4.同样,枚举
A
=
n
−
9
t
−
1
→
1
A=n-9t-1\rightarrow 1
A=n−9t−1→1.
5.同样,到这处理前缀和.
代码如下:
#include<bits/stdc++.h> using namespace std; #define Abigail inline void typedef long long LL; const int N=15000,M=40000; int n,m,x[M+9],num[4][N+9],cnt[N+9]; Abigail into(){ scanf("%d%d",&n,&m); for (int i=1;i<=m;i++){ scanf("%d",&x[i]); cnt[x[i]]++; } } Abigail work(){ int sum,A,B,C,D; for (int t=1;t*9<n;t++){ sum=0; for (D=9*t-2;D<=n;D++){ C=D-t; B=C-6*t-1; A=B-2*t; //知道D,计算出A,B,C sum+=cnt[A]*cnt[B]; //计算当前A和B的情况 num[2][C]+=cnt[D]*sum; //num[2][C]+=cnt[A]*cnt[B]*cnt[C] num[3][D]+=cnt[C]*sum; //num[3][D]+=cnt[A]*cnt[B]*cnt[D] } sum=0; for (A=n-9*t-1;A;A--){ B=A+2*t; C=B+6*t+1; D=C+t; //知道A,计算出B,C,D sum+=cnt[C]*cnt[D]; //计算当前C和D的情况 num[0][A]+=cnt[B]*sum; //num[0][A]+=cnt[B]*cnt[C]*cnt[D] num[1][B]+=cnt[A]*sum; //num[1][B]+=cnt[A]*cnt[C]*cnt[D] } } } Abigail outo(){ for (int i=1;i<=m;i++){ for (int j=0;j<3;j++) printf("%d ",num[j][x[i]]); printf("%d\n",num[3][x[i]]); } } int main(){ into(); work(); outo(); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。