首页 > 其他分享 >[AH2017HNOI2017] 礼物(fft)

[AH2017HNOI2017] 礼物(fft)

时间:2024-03-01 23:00:44浏览次数:29  
标签:le int sum fft 手环 temp1 AH2017HNOI2017 装饰物 礼物

[AH2017/HNOI2017] 礼物(fft)

题目描述

我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她。每个手环上各有 \(n\) 个装饰物,并且每个装饰物都有一定的亮度。

但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的非负整数 \(c\)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。

在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 \(1 \sim n\),其中 \(n\) 为每个手环的装饰物个数, 第 \(1\) 个手环的 \(i\) 号位置装饰物亮度为 \(x_i\),第 \(2\) 个手环的 \(i\) 号位置装饰物亮度为 \(y_i\),两个手环之间的差异值为(参见输入输出样例和样例解释):

\[\sum_{i=1}^{n} (x_i-y_i)^2 \]

麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小,这个最小值是多少呢?

数据范围

对于 \(30\%\) 的数据,\(n \le 500\),\(m \le 10\);

对于 \(70\%\) 的数据,\(n \le 5000\);

对于 \(100\%\) 的数据,\(1 \le n \le 50000\), \(1 \le a_i \le m \le 100\)。

解法

首先我们先列出来,其实就是求\(\sum_1^n[x_i^2+y_i^2+c^2+2*c(x_i-y_i)-x_i*y_i]\)

然后惊喜的发现,\(x_i^2\)与\(y_i^2\)是固定值,\(c^2+2*c(x_i-y_i)\)是一个二次函数,我们也能求出极值,而且注意他们的值是与序列顺序无关的。那么此时就剩下最后一项\(x_i*y_i\)了。我们只需要让这项最大即可。如果我们枚举对齐方式,然后再\(O(n)\)地计算其值,时间复杂度为\(O(n^2)\)。是显然我们无法接受的。

然后我们如果快速算呢,icpc澳门有一道题也用到了同样的处理,就是将其中一个数组倒置,然后进行卷积。假设我们从第0项构建多项式,那么第n-1项到第2n-1项的系数,即为我们\(On\)要求的值。此时因为用了fft,时间复杂度优化到\(O(nlogn)\)。即可通过此题。、

#include<bits/stdc++.h>
#define ll long long
#define i64 long long
using namespace std;
typedef complex<double> comp;
const int MAXN = 3000005;
comp A[MAXN], B[MAXN], ans[MAXN];
int rev[MAXN];
const comp I(0, 1);
const double PI = acos(-1);
void fft(comp F[], int N, int inv = 1)
{
    int bit = log2(N);
    for (int i = 0; i < N; ++i)
    {
        rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
        if (i < rev[i])
            swap(F[i], F[rev[i]]);
    }
    for (int l = 1; l < N; l *= 2) // 枚举合并前的区间长度
    {
        comp step = exp(inv * PI / l * I);
        for (int i = 0; i < N; i += l * 2) // 遍历起始点
        {
            comp cur(1, 0);
            for (int k = i; k < i + l; ++k)
            {
                comp g = F[k], h = F[k + l] * cur;
                F[k] = g + h, F[k + l] = g - h;
                cur *= step;
            }
        }
    }
    if (inv == -1)
        for (int i = 0; i < N; ++i)
            F[i] /= N;
}
void solve(){
    int n,m;cin>>n>>m;vector<int>a(n+1);vector<int>b(n+1);
    ll sum=0ll,temp1=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];sum+=a[i]*a[i];temp1+=a[i];
    }
    for(int i=1;i<=n;i++){
        cin>>b[i];sum+=1ll*b[i]*b[i];temp1-=b[i];
    }
    int n1=-floor(1.0*temp1/n);
    int n2=-ceil(1.0*temp1/n);;
    sum+=(ll)min(n1*n1*n+2*n1*temp1,n2*n2*n+2*n2*temp1);
    m=2*n-1;n--;
    int N = 1 << int(log2(n + m) + 1);
    for(int i=0;i<=m;i++)A[i]=a[n-(i%(n+1))+1];
    for(int i=0;i<=n;i++)B[i]=b[i+1];
    fft(A, N), fft(B, N);
    for (int i = 0; i < N; ++i)ans[i] = A[i] * B[i];
    fft(ans, N, -1);
    int temp2=int(ans[n].real() + 0.1);
    for (int i = n+1; i<=n+m; ++i){
        temp2=max(temp2,int(ans[i].real() + 0.1));
    }
    cout<<max(sum-2ll*temp2,0ll)<<"\n";
}
signed main(){
    std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
    srand((unsigned)time(NULL));
    //int t;cin>>t;while(t--)
    solve();
}

标签:le,int,sum,fft,手环,temp1,AH2017HNOI2017,装饰物,礼物
From: https://www.cnblogs.com/shi5/p/18048134

相关文章

  • Python报错symbol lookup error: xxx.so: undefined symbol: cufftxxx解决办法
    技术背景在上一篇文章中介绍过如何实现本地MindSpore的CUDA算子,那么在算子编译和使用的过程中可能会出现一些小问题,这里介绍的是编译成功为so动态链接库之后,在python中调用,提示找不到xxx函数/字符的报错。这里使用的编译指令为:$nvcc--shared-Xcompiler-fPIC-oxxx.soxxx.c......
  • FFT学习笔记
    目录FFT推荐博客大致流程复数运算DFT单位根(n等分)性质FFTIFFT递归版迭代版(蝴蝶变化)FFT推荐博客快速傅里叶变换(FFT)超详解浅谈FFT(终于懂一点了~~)十分简明易懂的FFT(快速傅里叶变换)题目链接:P3803【模板】多项式乘法(FFT)大致流程系数表示法<--O(NlongN)-->点值表示法点值表......
  • P2524 Uim的情人节礼物•其之弐 题解
    题目描述前传:详见洛谷P2525Uim成功地按照顺序将礼物送到了 N 个妹子的手里并维持她们的和谐。现在Uim现在想知道,他最终选择的顺序是所有给 N 个妹子送礼顺序中,字典序第几小的。送礼顺序可以看作1,2,⋯,N 的一个排列。输入格式第一行一个整数N,表示有 N 个数。第二......
  • 聊聊 fft 的单位根
    与ntt不同,处理fft的单位根要更加复杂,主要原因是考虑精度的问题.我们可以认为直接从三角函数计算出的单位根精度是最高的.当然由于\(\sin(x)\)和\(\cos(x)\)的渐进估计涉及到高次项,因此使用longdouble计算单位根再转成double是一点点意义的(如果longdouble精......
  • 【多项式】【模版】FFT NTT
    多项式若\(A(x)=a_0+a_1x+a_2x^2+\dotsa_nx^n(a_n\ne0)\),则称\(A\)是\(n\)次多项式。初中概念,但在OI中可以玩出花来。多项式的表示方式像上面的介绍一样,用系数\(a_0,a_1,\dotsa_n\)来表示多项式的方法称为系数表示法。还有一种表示多项式的方法,就是对于\(n\)......
  • 「JOI 2024 Final」礼物交换
    [link](https://loj.ac/p/4092)考虑单次询问怎么做。不难发现这是一个二分图匹配,左部点$i$可以匹配到右部点$j$当且仅当$A_i\geB_j\andi\neqj$。不妨设$B$递增,这当然可以通过排序实现。什么时候不存在完美匹配呢?就是存在左部点$i$,$i$只能匹配到右部点$[1,i-1]$(也......
  • P4721 【模板】分治 FFT
    最具经济性的写法:\(\mathcalO(n^2)\)暴力拿下\(80\)分,遂跑路。一题多解了,分两部分:分治和多项式求逆。分治考虑cdq分治,每次把\(f_{l\dotsmid}\)和\(g_{1\dotsn-1}\)卷起来,贡献直接加到\(f_{mid+1\dotsr}\)里,要注意一下顺序,先递归左区间,再算当前区间,最......
  • 洛谷题解-P1194 买礼物
    https://www.luogu.com.cn/problem/P1194题目描述又到了一年一度的明明生日了,明明想要买BBB样东西,巧的是,这BBB样东西价格都是AAA元。但是,商店老板说最近有促销活动,也就是:如果你买了第III样东西,再买第JJJ样,那么就可以只花KI,JK_{I,J}KI,J​元,更巧的是,KI,JK_{I,J}K......
  • FFT快速傅里叶变换
    傅里叶变换复数定义:x,y为实数,称形如(x,y)的有序数对为复数。复数(x,y)中的第一个实数x称为复数z的实部,第二个实数y称为复数z的虚部。代码实现及运算:structComplex{ doux,y; Complex(douxx=0,douyy=0){x=xx,y=yy;} Complexoperator+(Com......
  • FFT理论与习题
    参考了这篇博客,并且自己重新证了一下这篇博客中,笔者认为有误的IDFT中\(j\neqk\)的部分。第零部分·原理FFT是一种DFT的高效算法,称为快速傅里叶变换(fastFouriertransform),当然也可以用来算IDFT。这俩玩意前者可以把多项式从系数表达式转化成点值表达式,后者可以把点......