1 条题解

  • 0
    @ 2025-8-24 22:49:26

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar littlez_meow
    这个小z很懒,连这个家伙很懒都没有留下

    搬运于2025-08-24 22:49:26,当前版本为作者最后更新于2024-05-30 20:05:30,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    建议改为,偏导数在 OI 中的运用。

    题目指路

    题意

    给定 n,m,k,En,m,k,E 和长度分别为 n,mn,m 的序列 p1pn,q1qmp_1\sim p_n,q_1\sim q_m,记:

    $$f(x)=\sum\limits_{i=1}^k\left(a_i\cos(ix)+b_i\sin(ix)\right) $$$$\bar{u}=\frac{1}{n} \sum\limits_{i=1}^{n} f\left(p_{i}\right) $$$$\bar{v}=\frac{1}{m} \sum\limits_{j=1}^{m} f\left(q_{i}\right) $$$$\operatorname{cost}(f)=\frac{1}{\bar{u}-\bar{v}} \sqrt{\sum\limits_{i=1}^{n}\left(f\left(p_{i}\right)-\bar{u}\right)^{2}+\sum\limits_{j=1}^{m}\left(f\left(q_{j}\right)-\bar{v}\right)^{2}} $$

    你需要给出两个长为 kk 的序列 a1ak,b1bka_1\sim a_k,b_1\sim b_k,使得 uˉ>vˉ,cost(f)\bar{u}>\bar{v},\operatorname{cost}(f) 最小。绝对误差或相对误差小于 10E10^{-E}

    思路

    下面简记 cost(f)\operatorname{cost}(f)c(f)c(f)

    第一眼,cc 是一个函数到实数的映射。泛函?这怎么做?

    再想一想,其实 cc 的值只和 a1ak,b1bka_1\sim a_k,b_1\sim b_k2k2k 个取值有关。也就是说,cc 是一个 2k2k 元函数,记为 c(f)=c(a1,b1,,ak,bk)c(f)=c(a_1,b_1,\cdots,a_k,b_k)。很好,至少是个正常的函数了。

    uˉ>vˉ\bar{u}>\bar{v} 的限制太烦了,有没有什么办法能绕开呢?

    有!如果 uˉ<vˉ\bar{u}<\bar{v},我们直接把所有 ai,bia_i,b_i 全部乘 1-1。这样,函数值乘 1-1,方差不变,均值之差乘 1-1,此时的 uˉ>vˉ\bar{u}>\bar{v}

    也就是说,我们可以直接计算 c2(f)c^2(f)。这样,根号去掉了,uˉ<vˉ\bar{u}<\bar{v} 时的负数取值也去掉了。根据上面的论述,让 c(f)c(f) 取到最小值的 ff 也可以让 c2(f)c^2(f) 取到最小值。这容易用反证法证明。

    设 $C(f)=C(a_1,b_1,\cdots,a_k,b_k)=c^2(f)=\dfrac{\sum\limits_{i=1}^n(f(p_i)-\bar{u})^2+\sum\limits_{i=1}^m(f(q_i)-\bar{v})^2}{(\bar{u}-\bar{v})^2}$,我们只需要研究 C(f)C(f) 的最值就好了,且没有 uˉ>vˉ\bar{u}>\bar{v} 的要求。

    下一步怎么办呢?直接展开 uˉ,vˉ,f\bar{u},\bar{v},f?这样得到的结果会不会太复杂了呢?

    最小二乘法的经验告诉我们,我们可以尝试用向量和矩阵来描述上述式子,往往能大幅简化式子。

    2k2k 维向量 $\vec{t}=[a_1,b_1,\cdots,a_k,b_k]^T,\vec{f}(x)=[\cos(x),\sin(x),\cdots,\cos(kx),\sin(kx)]^T$。不难验证 f(x)=tf(x)f(x)=\vec t\cdot\vec f(x)。下面如果没有特殊说明,向量都是 2k2k 维的。

    现在 C(f)C(f) 就是一个关于 t\vec t 的函数了,记为 C(t)C(\vec t)

    pi=f(pi),qi=f(qi)\vec p_i=\vec f(p_i),\vec q_i=\vec f(q_i)。我们可以直接算出所有 pi,qi\vec p_i,\vec q_iC(f)C(f) 就跟 cos,sin\cos,\sin 没有半点关系了。

    现在来看看 uˉ\bar{u} 是怎么算出来的吧。

    写出原式:uˉ=1ni=1nf(pi)\bar u=\dfrac 1 n\sum\limits_{i=1}^nf(p_i)

    带入 f(x)=tf(x)f(x)=\vec t\cdot\vec f(x),得到:$\bar u=\dfrac 1 n\sum\limits_{i=1}^n\vec t\cdot\vec p_i$。

    使用向量点乘和加法的分配律:$\bar u=\vec t\cdot(\dfrac 1 n\sum\limits_{i=1}^n\vec p_i)$

    右边就是一个常向量了,记 r=1ni=1npi\vec r=\dfrac 1 n\sum\limits_{i=1}^n\vec p_i,则 uˉ=tr\bar u=\vec t\cdot\vec r

    同理,记 s=1mi=1mqi\vec s=\dfrac 1 m\sum\limits_{i=1}^m\vec q_i,则 vˉ=ts\bar v=\vec t\cdot\vec s

    现在,把这些向量带回原式:

    $$C(\vec t)=\dfrac{\sum\limits_{i=1}^n(\vec t\cdot(\vec p_i-\vec r))((\vec p_i-\vec r)\cdot\vec t)+\sum\limits_{i=1}^m(\vec t\cdot(\vec q_i-\vec s))((\vec q_i-\vec s)\cdot\vec t)}{(\vec t\cdot(\vec r-\vec s))^2} $$

    点积破坏了我们很多美好的性质,可不可以去掉它呢?

    对于列向量 a,b\vec a,\vec b,容易发现 aTb=[ab]\vec a^T\vec b=[\vec a\cdot\vec b]。我们只要认为 1×11\times1 的矩阵就是一个数,就可以用矩阵乘法代替点积。

    用矩阵乘法代替点积,使用结合律和分配律,得到:

    $$C(\vec t)=\dfrac{\vec t^T(\sum\limits_{i=1}^n(\vec p_i-\vec r)(\vec p_i-\vec r)^T+\sum\limits_{i=1}^m(\vec q_i-\vec s)(\vec q_i-\vec s)^T)\vec t}{\vec t^T((\vec r-\vec s)(\vec r-\vec s)^T)\vec t} $$

    好!中间括号里面的都变成常矩阵了!设矩阵 $A=\sum\limits_{i=1}^n(\vec p_i-\vec r)(\vec p_i-\vec r)^T+\sum\limits_{i=1}^m(\vec q_i-\vec s)(\vec q_i-\vec s)^T$,矩阵 B=(rs)(rs)TB=(\vec r-\vec s)(\vec r-\vec s)^T,我们就可以化简为:

    $$C(\vec t)=\dfrac{\vec t^TA\vec t}{\vec t^TB\vec t} $$

    非常美的一个结果。

    现在就是多元函数求最值问题了,方法是对每一元求偏导并使其等于 00

    Ai,jA_{i,j} 表示 AAii 行第 jj 列的元素,Bi,jB_{i,j} 同理。

    为了方便,设 x2i+1=ai,x2i=bix_{2i+1}=a_i,x_{2i}=b_i

    展开矩阵并化简,我们有:

    $$C(f)=\dfrac{\sum\limits_{i=1}^{2k}\sum\limits_{j=1}^{2k}x_ix_jA_{i,j}}{\sum\limits_{i=1}^{2k}\sum\limits_{j=1}^{2k}x_ix_jB_{i,j}} $$

    我们发现分子分母都是关于某个自变量的二次函数,容易求偏导。

    求导后,我们的结果中还存在一些高次项。加加减减消掉它们,我们发现系数又变成了矩阵的元素!只是等式右边带一个非零常数。即有以下方程:

    At=(rs)tA\vec t=(\vec r-\vec s)t

    这也是合理的。因为 a,ba,b 等比例放大,标准差也等比例放大,平均数同样等比例放大,在分式上的比例最后就消掉了。样例解释一也说明了这点。高斯消元解之即可。

    最后,还有高斯消元无解的情况。注意到数据范围里说 p,qp,q 随机生成,直接赌不会无解就好。

    时间复杂度 O(k3)O(k^3)k,n,mk,n,m 视为同阶。

    如果你的 p,qp,q 是整型,记得转成浮点型,否则你会因为溢出只有二十四分。

    代码

    #include<bits/stdc++.h>
    #define F(i,a,b) for(int i(a),i##i##end(b);i<=i##i##end;++i)
    #define R(i,a,b) for(int i(a),i##i##end(b);i>=i##i##end;--i)
    #define File(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
    #define ll long long
    using namespace std;
    const int MAXN=601;
    int n,m,k,kk,e,p[MAXN],q[MAXN];
    double vecp[MAXN][MAXN],vecq[MAXN][MAXN],r[MAXN],s[MAXN];
    double factor[MAXN][MAXN+1];
    double a[MAXN],b[MAXN];
    signed main(){
    	ios::sync_with_stdio(0);
    	cin.tie(0),cout.tie(0);
    	cin>>n>>m>>k>>e;
    	kk=k<<1;
    	F(i,1,n){
    		cin>>p[i];
    		F(j,1,k) r[(j<<1)-1]+=(vecp[i][(j<<1)-1]=cos(j*1.0*p[i])),r[j<<1]+=(vecp[i][j<<1]=sin(j*1.0*p[i]));
    	}
    	F(i,1,m){
    		cin>>q[i];
    		F(j,1,k) s[(j<<1)-1]+=(vecq[i][(j<<1)-1]=cos(j*1.0*q[i])),s[j<<1]+=(vecq[i][j<<1]=sin(j*1.0*q[i]));
    	}
    	F(i,1,kk) r[i]/=n,s[i]/=m,factor[i][kk+1]=r[i]-s[i];
    	F(i,1,kk) F(j,1,kk){
    		F(t,1,n) factor[i][j]+=(vecp[t][i]-r[i])*(vecp[t][j]-r[j]);
    		F(t,1,m) factor[i][j]+=(vecq[t][i]-s[i])*(vecq[t][j]-s[j]);
    	}
    	F(i,1,kk){
    		int mx=i;
    		F(j,i+1,kk) fabs(factor[j][i])>fabs(factor[mx][i])&&(mx=j);
    		swap(factor[i],factor[mx]);
    		F(j,i+1,kk){
    			double delta=factor[j][i]/factor[i][i];
    			F(t,i,kk+1) factor[j][t]-=factor[i][t]*delta;
    		}
    	}
    	R(i,kk,1){
    		if(i&1){
    			double&qwq=a[(i+1)>>1];
    			qwq=factor[i][kk+1]/factor[i][i];
    			R(j,i-1,1) factor[j][kk+1]-=qwq*factor[j][i];
    		}
    		else{
    			double&qwq=b[(i+1)>>1];
    			qwq=factor[i][kk+1]/factor[i][i];
    			R(j,i-1,1) factor[j][kk+1]-=qwq*factor[j][i];
    		}
    	}
    	double u=0,v=0;
    	F(i,1,k){
    		u+=r[(i<<1)-1]*a[i]+r[i<<1]*b[i];
    		v+=s[(i<<1)-1]*a[i]+s[i<<1]*b[i];
    	}
    	if(u<v) F(i,1,k) a[i]=-a[i],b[i]=-b[i];
    	cout<<fixed<<setprecision(12);
    	F(i,1,k) cout<<a[i]<<" "<<b[i]<<"\n";
    	return 0;
    } 
    
    • 1

    [湖北省选模拟 2023] 路环群山 / mountain

    信息

    ID
    9089
    时间
    2000ms
    内存
    512MiB
    难度
    7
    标签
    递交数
    0
    已通过
    0
    上传者