题目来源:http://www.fjutacm.com/Problem.jsp?pid=3283

题意:给两串长度为n的数组a和b,视为环,a和b可以在任意位置开始互相匹配得到这个函数的值,求这个函数的值最大是多少;

很明显是FFT,但是数据范围是n是1e5,a[i]和b[i]是1e6;精度会丢很多,也就是要NTT解决,那么要选一个不会影响答案的P,因为最大值为1e5*1e6*1e6;那么我们选一个1e17以上的就差不多了,然后就是求循环卷积的步骤,对此,我建议你们算一下这个,[a1、a2、a3、a1、a2、a3]*[b1、b2、b3],列出全部结果(乘法一样的操作,注意每一位乘法的偏移位置),你会发现得到的新集合去掉头上n-1个以及尾部n-1个就可以得到全部的线性卷积组合,那么我们就可以求那个两个数组的卷积得到的数组里直接找最大:

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll PMOD=(27ll<<)+, PR=;
const int N=1e6+;
static ll qp[];
ll res[N];
inline ll Mul(ll a,ll b){
if(a>=PMOD)a%=PMOD;
if(b>=PMOD)b%=PMOD;
return (a*b-(ll)(a/(long double)PMOD*b+1e-)*PMOD+PMOD)%PMOD;
}
struct NTT__container{
NTT__container( ){
int t,i;
for( i=; i<; i++){///注意循环上界与2n次幂上界相同
t=<<i;
qp[i]=quick_pow(PR,(PMOD-)/t);
}
}
ll quick_pow(ll x,ll n){
ll ans=;
while(n){
if(n&)
ans=Mul(ans,x);
x=Mul(x,x);
n>>=;
}
return ans;
}
int get_len(int n){///计算刚好比n大的2的N次幂
int i,len;
for(i=(<<); i; i>>=){
if(n&i){
len=(i<<);
break;
}
}
return len;
}
inline void NTT(ll F[],int len,int type){
int id=,h,j,k,t,i;
ll E,u,v;
for(i=,t=; i<len; i++){///逆位置换
if(i>t) swap(F[i],F[t]);
for(j=(len>>); (t^=j)<j; j>>=);
}
for( h=; h<=len; h<<=){///层数
id++;
for( j=; j<len; j+=h){///遍历这层上的结点
E=;///旋转因子
for(int k=j; k<j+h/; k++){///遍历结点上的前半序列
u=F[k];///A[0]
v=Mul(E,F[k+h/]);///w*A[1]
///对偶计算
F[k]=(u+v)%PMOD;
F[k+h/]=((u-v)%PMOD+PMOD)%PMOD;
///迭代旋转因子
E=Mul(E,qp[id]);///qp[id]是2^i等分因子
}
}
}
if(type==-){
int i;
ll inv;
for(i=; i<len/; i++)///转置,因为逆变换时大家互乘了对立点的因子
swap(F[i],F[len-i]);
inv=quick_pow(len,PMOD-);///乘逆元还原
for( i=; i<len; i++)
F[i]=Mul(F[i],inv);
}
}
void mul(ll x[],ll y[],int len){///答案存在x中
int i;
NTT(x,len,);///先变换到点值式
NTT(y,len,);///先变换到点值式上
for(i=; i<len; i++)
x[i]=Mul(x[i],y[i]);///在点值上点积
NTT(x,len,-);///再逆变换回系数式
}
} cal;
ll a[N], b[N];
int main() {
int n;
scanf("%d",&n);
for(int i=;i<n;i++)
scanf("%lld",a+i), a[i+n]=a[i];
for(int i=;i<n;i++)
scanf("%lld",&b[n--i]);
int len=cal.get_len(n+n+n);
cal.mul(a, b, len);
ll mx=;
for(int i=;i<len;i++){///完整的组合肯定更大所以说直接找最大
if(mx<a[i]){
mx=a[i];
}
}
printf("%lld\n",mx);
return ;
}

时间:1036MS 内存: 23632KB

还有优化的解法,这我真不知道为什么,可能是因为前后相加刚好可以组合出全部组合:

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll PMOD=(27ll<<)+, PR=;
const int N=1e6+;
static ll qp[];
ll res[N];
inline ll Mul(ll a,ll b){
if(a>=PMOD)a%=PMOD;
if(b>=PMOD)b%=PMOD;
//if(n<=1000000000)return a*b%n;
return (a*b-(ll)(a/(long double)PMOD*b+1e-)*PMOD+PMOD)%PMOD;
}
struct NTT__container{
NTT__container( ){
int t,i;
for(i=; i<; i++){///注意循环上界与2n次幂上界相同
t=<<i;
qp[i]=quick_pow(PR,(PMOD-)/t);
}
}
ll quick_pow(ll x,ll n){
ll ans=;
while(n){
if(n&)
ans=Mul(ans,x);
x=Mul(x,x);
n>>=;
}
return ans;
}
int get_len(const int &n){///计算刚好比n大的2的N次幂
int i, len;
for(i=(<<); i; i>>=){
if(n&i){
len=(i<<);break;
}
}
return len;
}
inline void NTT(ll F[], const int &len, int type){
int id=, h, j, t, i;
ll E,u,v;
for(i=,t=; i<len; i++){///逆位置换
if(i>t) swap(F[i],F[t]);
for(j=(len>>); (t^=j)<j; j>>=);
}
for( h=; h<=len; h<<=){///层数
id++;
for( j=; j<len; j+=h){///遍历这层上的结点
E=;///旋转因子
for(int k=j; k<j+h/; k++){///遍历结点上的前半序列
u=F[k];///A[0]
v=Mul(E,F[k+h/]);///w*A[1]
///对偶计算
F[k]=(u+v)%PMOD;
F[k+h/]=((u-v)%PMOD+PMOD)%PMOD;
///迭代旋转因子
E=Mul(E,qp[id]);///qp[id]是2^i等分因子
}
}
}
if(type==-){
int i;
ll inv;
for(i=; i<len/; i++)///转置,因为逆变换时大家互乘了对立点的因子
swap(F[i],F[len-i]);
inv=quick_pow(len,PMOD-);///乘逆元还原
for( i=; i<len; i++)
F[i]=Mul(F[i],inv);
}
}
void mul(ll x[],ll y[],int len){///答案存在x中
int i;
NTT(x,len,);///先变换到点值式
NTT(y,len,);///先变换到点值式上
for(i=; i<len; i++)
x[i]=Mul(x[i],y[i]);///在点值上点积
NTT(x,len,-);///再逆变换回系数式
}
} cal;
ll a[N], b[N];
int main() {
int n;
scanf("%d",&n);
for(int i=;i<n;i++)
scanf("%lld",a+i);
for(int i=;i<n;i++)
scanf("%lld",&b[n--i]);
int len=cal.get_len(n+n);
cal.mul(a, b, len);
ll mx=;
for(int i=;i<len;i++){
a[i]+=a[i+n];
if(mx<a[i]){
mx=a[i];
}
}
printf("%lld\n",mx);
return ;
}

时间:560MS 内存:23632KB

第八集:魔法阵 NTT求循环卷积的更多相关文章

  1. 【DFS】佳佳的魔法阵

    [vijos1284]佳佳的魔法阵 背景 也许是为了捕捉猎物(捕捉MM?),也许是因为其它原因,总之,佳佳准备设计一个魔法阵.而设计魔法阵涉及到的最关键问题,似乎就是那些带有魔力的宝石的摆放…… 描述 ...

  2. [NOIP2016普及组]魔法阵

    题目:洛谷P2119.Vijos P2012.codevs5624. 题目大意:有n件物品,每件物品有个魔法值.要求组成魔法阵(Xa,Xb,Xc,Xd),该魔法阵要满足Xa<Xb<Xc&l ...

  3. P2119 魔法阵

    原题链接  https://www.luogu.org/problemnew/show/P2119 YY同学今天上午给我们讲了这个题目,我觉得她的思路很好,特此写这篇博客整理一下. 50分:暴力枚举 ...

  4. 「Vijos 1284」「OIBH杯NOIP2006第二次模拟赛」佳佳的魔法阵

    佳佳的魔法阵 背景 也许是为了捕捉猎物(捕捉MM?),也许是因为其它原因,总之,佳佳准备设计一个魔法阵.而设计魔法阵涉及到的最关键问题,似乎就是那些带有魔力的宝石的摆放-- 描述 魔法阵是一个\(n ...

  5. 【做题记录】[NOIP2016 普及组] 魔法阵

    P2119 魔法阵 2016年普及组T4 题意: 给定一系列元素 \(\{X_i\}\) ,求满足以下不等式的每一个元素作为 \(a,b,c,d\) 的出现次数 . \[\begin{cases}X_ ...

  6. 洛谷 P2119 魔法阵

    题目描述 六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量. 大魔法师有mm个魔法物品,编号分别为1,2,...,m1,2,...,m.每个物品具有一个魔法值,我们用X_iXi ...

  7. [luogu2119]魔法阵 NOIP2016T4

    很好的一道数学推导题 45分做法 $O(N^4)$暴力枚举四个材料 55分做法 从第一个约束条件可得到所有可行答案都是单调递增的,所以可以排序一遍,减少枚举量,可以拿到55分 100分做法 首先可以发 ...

  8. ZOJ 3962 Seven Segment Display 16进制的八位数加n。求加的过程中所有的花费。显示[0,F]有相应花费。

    Seven Segment Display Time Limit: Seconds Memory Limit: KB A seven segment display, or seven segment ...

  9. 洛谷P2119 魔法阵

    P2119 魔法阵 题目描述 六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量. 大魔法师有m个魔法物品,编号分别为1,2,...,m.每个物品具有一个魔法值,我们用Xi表示编 ...

随机推荐

  1. Daily Scrum 12.22

    姓名 上周末任务 今日任务 刘垚鹏 完善和增加quiz页面的过滤功能 完善和增加quiz页面的过滤功能 王骜 对问答功能的修复 对问答功能的修复 林旭鹏 存储文件路径太长导致bug修复 存储文件路径太 ...

  2. 2-Sixteenth Scrum Meeting-20151216

    任务安排 成员 今日完成 明日任务 闫昊 写完学习进度记录的数据库操作  写完学习进度记录的数据库操作 唐彬 编写与服务器交互的代码  编写与服务器交互的代码 史烨轩 获取视频url   余帆  本地 ...

  3. 第二阶段Sprint7

    昨天:将“录制”及“保存”整合到一起,修复出现的Bug,使之能够正常运行. 今天:把视频录制整合到时间提醒里,实现视频提醒 遇到的问题:额,整进去直接就停止运行了..也没有报错..

  4. PAT 甲级 1085 Perfect Sequence

    https://pintia.cn/problem-sets/994805342720868352/problems/994805381845336064 Given a sequence of po ...

  5. WM_CONCAT和LISTAGG 语法例子

    select to_char(replace(wm_concat(name), ',', '')) from codeitems where setid = 'A018' and ' like cod ...

  6. RANCHER2.0 的简单使用

    1. RANCHER2.0  能够管理 k8s 集群 也能够用来搭建 k8s 集群 但是因为网络问题 只测试了如何去管理集群 还没有去 测试 安装集群. 2. 创建rancher 服务的方法 dock ...

  7. PSP(3.16——3.22)以及周记录

    3.17 13:30 14:45 15 60 讨论班 A Y min 14:50 17:05 5 130 得到设备 Cordova 蓝牙连接 A Y min 23:15 23:45 5 25 英语百词 ...

  8. 以太坊 链私有链环境搭建(windows)

    摸索以太坊区块链技术几个月了.最近打算逐步的把自己学到的东西和大家分享一下.在阅读本文之前,希望大家能对区块链的概念能有所了解.这样操作过程中的环节理解更深入.下面开始进入准备.因为本次是window ...

  9. 安利一个很火的 Github 滤镜项目

    安利一个很火的 Github 滤镜项目 园长 1 个月前 简评:通过深度学习,一秒钟让你的照片高大上,这是康奈尔大学和 Adobe 的工程师合作的一个新项目,通过卷积神经网络把图片进行风格迁移.项目已 ...

  10. POJ 1797 Heavy Transportation / SCU 1819 Heavy Transportation (图论,最短路径)

    POJ 1797 Heavy Transportation / SCU 1819 Heavy Transportation (图论,最短路径) Description Background Hugo ...