luogu P3321 [SDOI2015]序列统计 FFT
时间:2019-12-12
本文章向大家介绍luogu P3321 [SDOI2015]序列统计 FFT,主要包括luogu P3321 [SDOI2015]序列统计 FFT使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
首先数相同,位置不同的算作不同的方案,每多出一个位置就能多转移一次,所以我们可以写出这样的转移。
\(\displaystyle C[k]=\sum_{i\times j \%m==k}A[i]\times B[j]\)
我们平时写的FFT/NTT都是加号,这里是乘号,想要把乘号变成加号就要取\(log\),又因为是在mod m的意义下,m又是一个质数,所以我们可以找到m的原根,将原根作为底数,就能做多项式乘法了。
因为\(n\)比较大,所以要用多项式快速幂,当时我比较菜,还不会ln和exp的\(O(nlogn)\)快速幂,但实测\(O(nlog^2n)\)快速幂可过。
#include<iostream>
#include<cstdio>
//#define int long long
#define LL long long
using namespace std;
int n, m, x, s, tmp, k, tot;
const int N = 100010, mod = 1004535809, G = 3, Ginv = (mod + 1) / 3;
int r[N], mo[N], to[N];
LL F[N], ans[N];
int read()
{
char ch; int x = 0, f = 1;
while (!isdigit(ch = getchar())) {(ch == '-')&&(f = -f);}
while (isdigit(ch)) {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
return x * f;
}
LL ksm(LL a, LL b, LL mod)
{
LL res = 1;
for (; b; b >>= 1, a = a * a % mod)
if (b & 1)res = res * a % mod;
return res;
}
void NTT(LL *A, int lim, int opt)
{
for (int i = 0; i < lim; ++i)r[i] = (r[i >> 1] >> 1) | ((i & 1) ? (lim >> 1) : 0);
for (int i = 0; i < lim; ++i)
if (i < r[i])swap(A[i], A[r[i]]);
int len;
LL wn, w, x, y;
for (int mid = 1; mid < lim; mid <<= 1)
{
len = mid << 1;
wn = ksm(opt == 1 ? G : Ginv, (mod - 1) / len, mod);
for (int j = 0; j < lim; j += len)
{
w = 1;
for (int k = j; k < j + mid; ++k, w = w * wn % mod)
{
x = A[k]; y = A[k + mid] * w % mod;
A[k] = (x + y) % mod;
A[k + mid] = (x - y + mod) % mod;
}
}
}
if (opt == 1)return;
int ni = ksm(lim, mod - 2, mod);
for (int i = 0; i < lim; ++i)A[i] = A[i] * ni % mod;
}
void MUL(LL *A, int n, LL *B, int m, LL *C)
{
static LL X[N], Y[N];
int lim = 1;
while (lim <= (n + m))lim <<= 1;
for (int i = 0; i <= n; ++i)X[i] = A[i];
for(int i = n + 1;i <= lim;++ i)X[i]=0;
for (int i = 0; i <= m; ++i)Y[i] = B[i];
for(int i = m + 1;i <= lim;++ i)Y[i]=0;
NTT(X, lim, 1); NTT(Y, lim, 1);
for (int i = 0; i < lim; ++i)X[i] = X[i] * Y[i] % mod;
NTT(X, lim, -1);
for (int i = 0; i < m - 1; ++i)X[i] = (X[i] + X[i + m - 1]) % mod;
for (int i = 0; i < m - 1; ++i)C[i] = X[i];
}
int GET_ROOT(int m)
{
tot = 0;
int tmp = m - 1;
for (int i = 2; i * i <= tmp; ++i)
if (!(tmp % i))
{
mo[++tot] = i;
while (!(tmp % i))tmp /= i;
}
if (tmp != 1)mo[++tot] = tmp;
bool flag;
for (int i = 2; i <= m; ++i)
{
flag = 1;
for (int j = 1; j <= tot; ++j)
if (ksm(i, (m - 1) / mo[j], m) == 1)
{
flag = 0;
break;
}
if (flag)return i;
}
return -1;
}
void YYCH(LL *A, int b, LL *c)
{
c[to[1]] = 1;
for (; b; b >>= 1, MUL(A, m, A, m, A))
if (b & 1)MUL(A, m, c, m, c);
}
signed main()
{
cin >> n >> m >> x >> s;
k = GET_ROOT(m);
tmp = 1;
for (int i = 0; i < m - 1; ++i, tmp = tmp * k % m)to[tmp] = i;
for (int i = 1; i <= s; ++i)
{
tmp = read();
if (tmp)F[to[tmp]]++;
}
YYCH(F, n, ans);
cout << ans[to[x]];
return 0;
}
原文地址:https://www.cnblogs.com/wljss/p/12029009.html
- 如何在5分钟内做出你的第一个开源贡献
- [喵咪大数据]HUE大数据管理工具
- Dubbo源码解析 —— Zookeeper 订阅
- 注册中心 Eureka 源码解析 —— 项目结构简介
- 【平台】Seldon.io发布新开源平台,用于Kubernetes上的机器学习
- 分布式事务 TCC-Transaction 源码分析 —— TCC 实现
- 了解学习速率以及它如何提高深度学习的表现
- 分布式消息队列 RocketMQ源码解析:事务消息
- WordPress用Windows主机设置伪静态方法
- PHP页面跳转代码
- 分布式事务 TCC-Transaction 源码解析 —— 调试环境搭建
- 机器学习入门——使用python进行监督学习
- 推荐算法的介绍,第一部分——协同过滤与奇异值分解
- 在ASP中实现UNIX时间戳
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android读取资源文件的方法
- Android 基于IntentService的文件下载的示例代码
- Android开发之底图局部加载移动的方法示例
- Ubuntu18.04下解决Qt出现qt.qpa.plugin:Could not load the Qt platform plugin “xcb“问题
- ExpandableListView实现手风琴效果
- 组复制性能 | 全方位认识 MySQL 8.0 Group Replication
- Android 中View.onDraw(Canvas canvas)的使用方法
- Android API编程之Assets文件操作示例
- Android自制精彩弹幕效果
- RollViewPager无限轮播使用方法详解
- ubuntu16.04 升级内核的方法步骤
- Android 列表倒计时的实现的示例代码(CountDownTimer)
- Android 控件设置阴影效果
- 解决VScode配置远程调试Linux程序的问题
- Android EasyBarrage实现轻量级弹幕效果