题目链接  51nod 算法马拉松 34  Problem D

在这个题中$2$这个质数比较特殊,所以我们先特判$2$的情况,然后仅考虑大于等于$3$的奇数即可。

首先考虑任意一个点对$(i, j)$,满足$1 <= i <= j <= n$

我们考虑这个点对对答案的贡献。

首先显然$i$和$j$必须有相同的奇偶性,那么$i + j$一定为偶数。

包含这个点对的有效的质数的区间长度为$[j - i + 1, min(i + j - 1, 2n + 1 - i - j)]$中的所有质数。

(就假设以这个区间为中心,一点点向外扩,直到左边界碰到$1$或者右边界碰到$n$位置)

设$f(x)$为前$x$个数中的质数个数(这里我们假设$2$不是质数),

那么这个点对对答案的贡献为$f_{min(i + j - 1, 2n + 1 - i - j)} * ∑a_{i} * a_{j} - f_{j - i} * ∑a_{i} * a_{j}$

现在分类讨论

  • 当$i + j - 1 <= n$时,$min(i + j - 1, 2n + 1 - i - j) = i + j - 1$, 贡献为$f_{i + j - 1} * ∑a_{i} * a_{j} - f_{j - i} * ∑a_{i} * a_{j}$
  • 当$i + j - 1  >  n$时,$min(i + j - 1, 2n + 1 - i - j) = 2n + 1 - i - j$, 贡献为$f_{2n + 1 - i - j} * ∑a_{i} * a_{j} - f_{j - i} * ∑a_{i} * a_{j}$

可以发现两种情况对于减掉的部分是一样的,那么合起来考虑。

对于那些贡献为正的部分,$∑a_{i} * b_{j}$用FFT加速卷积就可以求出;

对于那些贡献为负的部分,我们其实要求的就是$s_{j} * ∑a_{i} * a_{i - j}$,

令$b_{i} = a_{n - i + 1}$,那么问题转化成了求$a$和$b$的卷积和,问题也解决了。

时间复杂度$O(nlogn)$

我本来想用NTT,结果TLE了整整一天,准备放弃的时候发现FFT足够了,我真笨

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const double PI = acos(-1.0);
const int N = (1 << 18) + 10;
const LL mod = 1e9 + 7; int s[N];
int n;
int cnt = 0;
LL ans;
LL a[N], b[N], c[N]; struct Complex{
double x, y;
Complex(double x = 0.0, double y = 0.0) : x(x), y(y){}
Complex operator + (const Complex &b) const{
return Complex(x + b.x, y + b.y);
}
Complex operator - (const Complex &b) const{
return Complex(x - b.x, y - b.y);
}
Complex operator * (const Complex &b) const{
return Complex(x * b.x - y * b.y, x * b.y + y * b.x);
}
}; Complex x1[N << 1], x2[N << 1]; void change(Complex y[], int len){
for (int i = 1, j = len / 2; i < len - 1; i++){
if (i < j) swap(y[i], y[j]);
int k = len / 2;
while (j >= k){
j -= k;
k /= 2;
}
if (j < k) j += k;
}
} void fft(Complex y[], int len, int on){
change(y, len);
for (int h = 2; h <= len; h <<= 1){
Complex wn(cos(-on * 2 * PI / h), sin(-on * 2 * PI / h));
for (int j = 0; j < len; j += h){
Complex w(1, 0);
for (int k = j; k < j + h / 2; k++){
Complex u = y[k];
Complex t = w * y[k + h / 2];
y[k] = u + t;
y[k + h / 2] = u - t;
w = w * wn;
}
}
} if (on == -1){
rep(i, 0, len - 1) y[i].x /= len;
}
} void mul(LL p[], int dp, LL q[], int dq){
int len = 1;
while (len <= dp + dq) len <<= 1; rep(i, 0, dp) x1[i] = Complex(p[i], 0);
rep(i, dp + 1, len - 1) x1[i] = Complex(0, 0); rep(i, 0, dq) x2[i] = Complex(q[i], 0);
rep(i, dq + 1, len - 1) x2[i] = Complex(0, 0); fft(x1, len, 1);
fft(x2, len, 1); rep(i, 0, len - 1) x1[i] = x1[i] * x2[i];
fft(x1, len, -1);
rep(i, 0, dp + dq) c[i] = (LL)(x1[i].x + 0.5), c[i] %= mod;
} int main(){ rep(i, 3, (1 << 18)){
int bl = sqrt(i), flag = 1;
rep(j, 2, bl) if (i % j == 0){
flag = 0;
break;
} s[i] = s[i - 1] + flag;
} scanf("%d", &n);
ans = 0; rep(i, 1, n){
scanf("%lld", a + i);
b[i] = a[i];
} mul(a, n, b, n); rep(i, 1, n - 1){
ans += a[i] * a[i + 1] % mod * 2 % mod;
if (ans > mod) ans -= mod;
} rep(i, 4, n + 1){
if (i & 1) continue;
ans = ans + c[i] * s[i - 1] % mod;
if (ans > mod) ans -= mod;
} rep(i, n + 2, n + n){
if (i & 1) continue;
ans = ans + c[i] * s[2 * n + 1 - i] % mod;
if (ans > mod) ans -= mod;
} reverse(b + 1, b + n + 1);
mul(a, n, b, n); rep(i, 0, n - 1){
if (i & 1) continue;
ans = ans - c[i + n + 1] * s[i] % mod * 2 % mod;
ans += mod;
ans %= mod;
} printf("%lld\n", ans);
return 0;
}

  

51nod 算法马拉松 34 Problem D 区间求和2 (FFT加速卷积)的更多相关文章

  1. 51NOD 算法马拉松8

    题目戳这里:51NOD算法马拉松8 某天晚上kpm在玩OSU!之余让我看一下B题...然后我就被坑进了51Nod... A.还是01串 水题..怎么乱写应该都可以.记个前缀和然后枚举就行了.时间复杂度 ...

  2. 随便玩玩系列之一:SPOJ-RNG+51nod 算法马拉松17F+51nod 1034 骨牌覆盖v3

    先说说前面的SPOJ-RNG吧,题意就是给n个数,x1,x2,...,xn 每次可以生成[-x1,x1]范围的浮点数,把n次这种操作生成的数之和加起来,为s,求s在[A,B]内的概率 连续形的概率 假 ...

  3. 51Nod 算法马拉松21(迎新年)

    这次打算法马拉松是在星期五的晚上,发挥还算正常(废话,剩下的题都不会= =). 讲讲比赛经过吧. 8:00准时发题,拿到之后第一时间开始读. A配对,看上去像是二分图最大权匹配,一看范围吓傻了,先跳过 ...

  4. 51Nod 算法马拉松23 开黑记

    惨啊……虽然开了半天黑,但是还是被dalao们踩了…… 第二次开黑,还是被卡在rank20了,我好菜啊……= = 写一写比赛经过吧…… 看到题之后习惯性都打开,A~D看上去似乎并没有什么思路,F应该是 ...

  5. 51Nod 算法马拉松22 开黑记

    这是一场惨烈的开黑大战,始于全机房开黑指望刷进rank前十拿钱的壮志,终于被各路神犇怒踩成rank20,差点200点头盾不保的落魄,想起将近一年前ad和zcg等学长挤进rank10的壮举,不由得唏嘘, ...

  6. 51Nod 算法马拉松15 记一次悲壮而又开心的骗分比赛

    OwO 故事的起源大概是zcg前天发现51Nod晚上有场马拉松,然后他就很开心的过去打了 神奇的故事就开始了: 晚上的时候我当时貌似正在写线段树?然后看见zcg一脸激动告诉我第一题有九个点直接输出B就 ...

  7. 51nod算法马拉松 contest7

    A题 链接:http://www.51nod.com/contest/problem.html#!problemId=1417 推荐链接:http://blog.csdn.net/a837199685 ...

  8. 51nod算法马拉松12

    A 第K大区间 不妨考虑二分答案x,则问题转化成计算有多少个区间满足众数出现的次数>=x. 那么这个问题我们使用滑动窗口,枚举右端点,则左端点肯定单调递增,然后维护一个简单的数组就能资瓷添加元素 ...

  9. 51NOD 算法马拉松12

    OTZ做出题目的神犇..断断续续改完了在这里存一下思路吧 A题:第K大区间题意:定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. 分析:二分答案mid,任务 ...

随机推荐

  1. 《Cracking the Coding Interview》——第9章:递归和动态规划——题目10

    2014-03-20 04:15 题目:你有n个盒子,用这n个盒子堆成一个塔,要求下面的盒子必须在长宽高上都严格大于上面的.如果你不能旋转盒子变换长宽高,这座塔最高能堆多高? 解法:首先将n个盒子按照 ...

  2. CMDB项目实战

    01-CMDB项目介绍 02-CMDB开发背景 03-CMDB开发目的 04-CMDB资产采集方式之agent 05-CMDB资产采集方式之ssh 06-CMDB资产采集方式之saltstack 07 ...

  3. python 学习分享-socket编程

    socket的英文原义是“孔”或“插座”.作为BSD UNIX的进程通信机制,取后一种意思. 通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟 ...

  4. PAT——甲级1009:Product of Polynomials;乙级1041:考试座位号;乙级1004:成绩排名

    题目 1009 Product of Polynomials (25 point(s)) This time, you are supposed to find A×B where A and B a ...

  5. tomcat集群和负载均衡的实现(session同步)

      (一)环境说明 (1)服务器有4台,一台安装apache,三台安装tomcat (2)apache2.0.55.tomcat5.5.15.jk2.0.4.jdk1.5.6或jdk1.4.2 (3) ...

  6. 会话管理 session实现多页面传输数据

    以下面购物车几个页面传输数据为例html页面有index.html <!DOCTYPE html> <html lang="en"> <head> ...

  7. [AT2699]Flip and Rectangles

    题目大意:有一个$n\times m$的$01$矩阵,可以把任意行或列反转,问最大的全为一的子矩阵的面积 题解:有一个结论:若一个子矩形$S$中的任意一个$2\times 2$的子矩形都含有偶数个$1 ...

  8. BZOJ1055[HAOI2008]玩具取名 【区间dp + 记忆化搜索】

    题目 某人有一套玩具,并想法给玩具命名.首先他选择WING四个字母中的任意一个字母作为玩具的基本名字.然后 他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够 ...

  9. stringutil的方法

    StringUtils 源码,使用的是commons-lang3-3.1包. 下载地址 http://commons.apache.org/lang/download_lang.cgi 以下是Stri ...

  10. 向mysql中批量插入数据的性能分析

    MYSQL批量插入数据库实现语句性能分析 假定我们的表结构如下 代码如下   CREATE TABLE example (example_id INT NOT NULL,name VARCHAR( 5 ...