zoukankan      html  css  js  c++  java
  • 并不对劲的bzoj4827:loj2020:p3723:[AHOI/HNOI2017]礼物

    题目大意

    有两个长度为(n)((nleq5*10^4))的数列(x_1,x_2,...,x_n)(y_1,y_2,...,y_n),两个数列里的数都不超过(m)((mleq100))
    现在可以进行“(1)把(x)中的所有数同时加上一个值”和“(i<n)时,((2)x_i)变成(x_{i+1})(i=n)时,(x_i)变成(x_1)”这两种操作
    操作任意次,使(Sigma_{i=1}^{n}{(x_i-y_i)^2})最小

    题解

    设(1)操作加上的值为(k),(2)操作执行了(j)次;定义(add(a,b))(a+bleq n)时为(a+b),否则为(a+b-n)
    那么就是要选出合适的(k,j),使(Sigma_{i=1}^{n}{(x_i+k-y_{add(i,j)})^2})最小
    该式=(Sigma_{i=1}^{n}{(x_i^2+k^2-y_{add(i,j)}^2+2*x_i*k-2*x_i*y_{add(i,j)}-2*k*y_{add(i,j)})})
    =((Sigma_{i=1}^{n}x_i^2)+(Sigma_{i=1}^{n}y_i^2)+n*k^2+(Sigma_{i=1}^{n}{(2*x_i*k-2*x_i*y_{add(i,j)}-2*k*y_{add(i,j)})}))
    其中((Sigma_{i=1}^{n}x_i^2)+(Sigma_{i=1}^{n}y_i^2))是定值,要让剩下的部分(n*k^2+(Sigma_{i=1}^{n}{(2*x_i*k-2*x_i*y_{add(i,j)}-2*k*y_{add(i,j)})}))更小
    该式=(n*k^2+(Sigma_{i=1}^{n}{(2*k*(x_i-y_{add(i,j)})-2*x_i*y_{add(i,j)}}))
    =(n*k^2+(Sigma_{i=1}^{n}{2*k*(x_i-y_{add(i,j)})})-(Sigma_{i=1}^{n}{2*x_i*y_{add(i,j)}}))
    =(n*k^2+2*k*((Sigma_{i=1}^{n}{x_i})-(Sigma_{i=1}^{n}{y_i}))-(Sigma_{i=1}^{n}{2*x_i*y_{add(i,j)}}))
    将它分成两部分,第一部分是(n*k^2+2*k*((Sigma_{i=1}^{n}{x_i})-(Sigma_{i=1}^{n}{x_i}))),第二部分是((Sigma_{i=1}^{n}{2*x_i*y_{add(i,j)}}))
    第一部分只和(k)有关,第二部分只和(j)有关
    那就可以分别算出(k)(-m)(m)时第一部分的取值,分别算出(j)(0)(n-1)时第二部分的取值,再枚举(k,j)的值
    发现第二部分是个卷积式,算这部分的时间复杂度围为(Theta(n*log n))
    总时间复杂度是(Theta(n*log n+n*m))

    代码
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
    #define maxn 50010
    #define maxm (maxn*6)
    #define inf 2147483647
    #define LL long long
    using namespace std;
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)&&ch!='-')ch=getchar();
    	if(ch=='-')f=-1,ch=getchar();
    	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return x*f;
    }
    void write(int x)
    {
    	if(x==0){putchar('0'),putchar('
    ');return;}
    	int f=0;char ch[20];
    	if(x<0)putchar('-'),x=-x;
    	while(x)ch[++f]=x%10+'0',x/=10;
    	while(f)putchar(ch[f--]);
    	putchar('
    ');
    	return;
    }
    const LL mod = 998244353;
    int ans,m,n,fakeans[maxn],x[maxn],y[maxn],sumx,sumy,ans2,a[maxm],b[maxm],nown,len,r[maxm]; 
    int mul(int x,int y){int res=1;while(y){if(y&1)res=(LL)res*(LL)x%mod;x=(LL)x*(LL)x%mod,y>>=1;}return res;}
    void dnt(int * c,int f)
    {
    	rep(i,0,nown-1){r[i]=(r[i>>1]>>1)|((i&1)<<(len-1));}
    	rep(i,0,nown-1){if(i<r[i])swap(c[i],c[r[i]]);}
    	for(int i=1;i<nown;i<<=1)
    	{
    		int wn=mul(3,(mod-1)/(i<<1)),xx,yy;
    		if(f==-1)wn=mul(wn,mod-2);
    		for(int j=0;j<nown;j+=(i<<1))
    		{
    			int w=1;
    			rep(k,0,i-1)xx=c[j+k]%mod,yy=(LL)w*(LL)c[j+i+k]%mod,c[j+k]=(xx+yy)%mod,c[j+i+k]=(xx-yy+mod)%mod,w=(LL)w*(LL)wn%mod;
    		}
    	}
    	if(f==-1){int inv=mul(nown,mod-2);rep(i,0,nown-1)c[i]=(LL)c[i]*(LL)inv%mod;}
    }
    int main()
    {
    	n=read(),m=read();
    	rep(i,1,n)x[i]=read(),sumx+=x[i],ans2+=x[i]*x[i];
    	rep(i,1,n)y[i]=read(),sumy+=y[i],ans2+=y[i]*y[i];
    	rep(i,0,n-1)a[i]=x[i+1];
    	rep(i,n,(n<<1)-1)a[i]=x[i-n+1];
    	rep(i,0,n)b[i]=y[n-i]*2;
    	for(nown=1,len=0;nown<(n+n+n-1);nown<<=1)len++;
    	dnt(a,1),dnt(b,1);
    	rep(i,0,nown-1)a[i]=(LL)a[i]*(LL)b[i]%mod;
    	dnt(a,-1);
    	rep(i,0,n-1)fakeans[i]=a[i+n-1];
    	ans=inf;	
    	rep(k,-m,m)rep(j,0,n-1)ans=min(ans,2*k*(sumx-sumy)+n*k*k-fakeans[j]);
    	write(ans+ans2);
    	return 0;
    }
    /*
    5 6
    1 2 3 4 5
    6 3 3 4 5
    */
    
    一些感想

    还有一百天左右!

  • 相关阅读:
    防止软件被暴力破解
    简单分析QQ群验证
    Hash(哈希)算法科普
    C语言自学的方法
    如何防范算法求逆
    .Net程序逆向入门教程
    分享几篇VMP研究和分析的文章
    逆向工程
    PHP之MVC项目实战(三)
    PHP之MVC项目实战(二)
  • 原文地址:https://www.cnblogs.com/xzyf/p/10420397.html
Copyright © 2011-2022 走看看