BZOJ 3992 [SDOI 2015] 序列统计 解题报告
这个题最暴力的搞法就是这样的:
设 $Dp[i][j]$ 为前 $i$ 个数乘积为 $j$ 的方案数。
转移的话就不多说了哈。。。
当前复杂度 $O(nm^2)$
注意到,$M$ 是个质数,就说明 $M$ 有原根并且我们可以很快的求出来。
于是对于 $1\rightarrow M-1$ 中的每一个数都可以表示成原根的某次幂。
于是乘法可以转化为原根的幂的加法,
转移的时候就相当于做多项式乘法了。
我们再注意到,$1004535809 = 479 \times 2^{21} + 1$ 并且是个质数,原根为 $3$。
于是转移的时候就可以用 $FFT$ 优化了。
当前复杂度 $O(nm\log m)$
我们再考虑,每次多项式乘法中乘的多项式都是一样的,那么是不是就可以快速幂啊?
当前复杂度 $O(m\log m\log n)$,可以 A 掉这个题啦~
注意那些等于 $0$ 的数。。。
具体细节自己脑补脑补吧~
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
#define N 16384 + 5
#define Mod 1004535809
#define g 3 int n, p, x, m, len, w, d, root, inv_len, ans;
int T[N], Num[N], Pos[N];
int A[N], B[N], C[N], Rev[N], e[][N]; inline int power(int u, int v, int p)
{
int res = ;
for (; v; v >>= )
{
if (v & ) res = (LL) res * u % p;
u = (LL) u * u % p;
}
return res;
} inline void Init()
{
scanf("%d%d%d%d", &n, &p, &x, &m);
for (int i = ; i <= m; i ++)
scanf("%d", T + i);
for (len = p << ; len != (len & -len); len += (len & -len)) ;
for (int i = len; i > ; i >>= ) d ++;
inv_len = power(len, Mod - , Mod);
w = power(g, (Mod - ) / len, Mod);
} inline bool Judge(int x, int p)
{
for (int i = ; i * i <= p; i ++)
if ((p - ) % i == && power(x, (p - ) / i, p) == ) return ;
return ;
} inline int Find_Root(int p)
{
if (p == ) return ;
int res = ;
for (; !Judge(res, p); res ++) ;
return res;
} inline void Prepare()
{
root = Find_Root(p);
for (int i = ; i < p - ; i ++)
{
Num[i] = !i ? : Num[i - ] * root % p;
Pos[Num[i]] = i;
}
} inline int Inc(int u, int v)
{
return u + v - (u + v >= Mod ? Mod : );
} inline void FFT(int *Ar, int op)
{
for (int i = ; i < len; i ++)
if (Rev[i] > i) swap(Ar[i], Ar[Rev[i]]);
for (int k = , s = ; k < len; k <<= , s ++)
for (int i = ; i < len; i ++)
{
if (i & k) continue ;
int t = (i & k - ) << d - s;
int u = Inc(Ar[i], (LL) Ar[i + k] * e[op][t] % Mod);
int v = Inc(Ar[i], Mod - ((LL) Ar[i + k] * e[op][t] % Mod));
Ar[i] = u, Ar[i + k] = v;
}
} inline void Convol(int *U, int *V)
{
for (int i = ; i < len; i ++)
C[i] = V[i];
FFT(U, ), FFT(C, );
for (int i = ; i < len; i ++)
U[i] = (LL) U[i] * C[i] % Mod;
FFT(U, );
for (int i = ; i < len; i ++)
U[i] = (LL) U[i] * inv_len % Mod;
for (int i = len - ; i >= p - ; i --)
{
U[i - p + ] = Inc(U[i - p + ], U[i]);
U[i] = ;
}
} inline void Solve()
{
A[] = ;
for (int i = ; i <= m; i ++)
{
if (T[i] == ) continue ;
B[Pos[T[i]]] ++;
}
for (int i = , inv_w = power(w, Mod - , Mod); i < len; i ++)
{
e[][i] = !i ? : (LL) e[][i - ] * w % Mod;
e[][i] = !i ? : (LL) e[][i - ] * inv_w % Mod;
for (int j = ; j < d; j ++)
if ((i >> j) & ) Rev[i] += << (d - j - );
}
for (; n; n >>= )
{
if (n & ) Convol(A, B);
Convol(B, B);
}
ans = A[Pos[x]];
} int main()
{
#ifndef ONLINE_JUDGE
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
#endif Init();
Prepare();
Solve();
printf("%d\n", ans); #ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return ;
}
3992_Gromah
BZOJ 3992 [SDOI 2015] 序列统计 解题报告的更多相关文章
- [BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT)
[BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT) 题面 小C有一个集合S,里面的元素都是小于质数M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数 ...
- [BZOJ 3992] [SDOI 2015] 序列统计
Description 传送门 Solution [一] 设 \(f[i][j]\) 表示前 \(i\) 个数的乘积在模 \(p\) 意义下等于 \(j\) 的方案数,有 \[ f[i][j]=\su ...
- BZOJ 3993 [SDOI 2015] 星际战争 解题报告
首先我们可以二分答案. 假设当前二分出来的答案是 $Ans$ ,那么我们考虑用网络流检验: 设武器为 $X$,第 $i$ 个武器的攻击力为 $B_i$: 设机器人为 $Y$,第 $i$ 个机器人的装甲 ...
- 【SDOI2015】序列统计 解题报告
2119: [BZOJ3992][SDOI2015]序列统计 Description 小\(C\)有一个集合\(S\),里面的元素都是小于\(M\)的非负整数. 他用程序编写了一个数列生成器,可以生成 ...
- [SDOI 2015]序列统计
Description 题库链接 给出集合 \(S\) ,元素都是小于 \(M\) 的非负整数.问能够生成出多少个长度为 \(N\) 的数列 \(A\) ,数列中的每个数都属于集合 \(S\) ,并且 ...
- BZOJ 4004 [JLOI 2015] 装备购买 解题报告
哎这个题 WA 了无数遍...果然人太弱... 首先我们把这些装备按照花费从小到大排序,然后依次考虑是否能买这个装备. 至于这样为什么是对的,好像有一个叫拟阵的东西可以证明,然而我不会.TATQAQ ...
- 【BZOJ 4403】 4403: 序列统计 (卢卡斯定理)
4403: 序列统计 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 653 Solved: 320 Description 给定三个正整数N.L和R, ...
- BZOJ 3990 [SDOI 2015] 排序 解题报告
这个题哎呀...细节超级多... 首先,我猜了一个结论.如果有一种排序方案是可行的,假设这个方案是 $S$ . 那么我们把 $S$ 给任意重新排列之后,也必然可以构造出一组合法方案来. 于是我们就可以 ...
- 洛谷 P1110 [ZJOI2007]报表统计 解题报告
P1110 [ZJOI2007]报表统计 题目描述 \(Q\)的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小\(Q\)希望可以帮妈妈分担一些工作,作为她的生日礼物之一. 经过仔细 ...
随机推荐
- C语言的一些误用和知识总结
现在学嵌入式的话,最主要是要把C语言熟悉,比如指针,链表,共用体,结构体等,还是得听老师的话.. 在学习单片机的时候才真正知道C语言是什么它是来干什么的~但是C语言用到嵌入式只是它小小的一部分他的应用 ...
- 用CentOS 7打造合适的科研环境
http://seisman.info/linux-environment-for-seismology-research.html 这篇博文记录了我用CentOS 7搭建地震学科研环境的过程,供我个 ...
- DEDECMS 获取当前栏目及所有子栏目的文章数量
因DEDEV5起,加强了对SQL注入和安全的检查,导致无法查询一些正常的子查询的SQL. 以下代码用来解决查询当前栏目及当前栏目下所有子栏目的文章总数,添加到/include/common.func. ...
- XML DOM操作,适用目前流行的浏览器
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
- SSH免密码登录设置
我们使用ssh-keygen在ServerA上生成private和public密钥,将生成的public密钥拷贝到远程机器ServerB上后,就可以使用ssh命令无需密码登录到另外一台机器Server ...
- 第三章 jQuery中的DOM操作
DOM(Document Object Model)文档对象模型,每张网页都能用DOM表示出来,每一份DOM都能看成一颗DOM树. jQuery继承了JavaScript对DOM对象操作的特性,使开发 ...
- MongoDB 的分组操作 In C#
C#对mongodb的分组查询操作,主要通过脚本或Aggregate方法来实现,以下通过一些实例作解析: 参考资料:http://www.tuicool.com/articles/2iqUZj h ...
- 20160505-hibernate入门2
基本概念和CURD 开发流程 1由Domain object -> mapping->db.(官方推荐) 2由DB开始,用工具生成mapping和Domain object.(使用较多) ...
- java中的拷贝文件FileChannel
以前用Java拷贝文件,只知道写byte数组循环拷贝,今天知道了可以用FileChannel进行拷贝,上代码: 下边是传统的byte数组拷贝方法 </pre><pre name=&q ...
- 对象创建型模式------Builder(生成器或建造者模式)(2)
链接转自:http://blog.csdn.net/wuzhekai1985/article/details/6667467 主要思想是:首先有个指挥家思想者将大体的设计思路设计出来,然后寻找一部分工 ...