板子题都差点不会了

Description

小C有一个集合S,里面的元素都是小于M的非负整数。他用程序编写了一个数列生成器,可以生成一个长度为N的数
列,数列中的每个数都属于集合S。小C用这个生成器生成了许多这样的数列。但是小C有一个问题需要你的帮助:
给定整数x,求所有可以生成出的,且满足数列中所有数的乘积mod M的值等于x的不同的数列的有多少个。小C认为
,两个数列{Ai}和{Bi}不同,当且仅当至少存在一个整数i,满足Ai≠Bi。另外,小C认为这个问题的答案可能很大
,因此他只需要你帮助他求出答案mod 1004535809的值就可以了。

Input

一行,四个整数,N、M、x、|S|,其中|S|为集合S中元素个数。
第二行,|S|个整数,表示集合S中的所有元素。
1<=N<=10^9,3<=M<=8000,M为质数
0<=x<=M-1,输入数据保证集合S中元素不重复x∈[1,m-1]

集合中的数∈[0,m-1]

Output

一行,一个整数,表示你求出的种类数mod 1004535809的值。


题目分析

用$f_{i,j}$表示选了$i$个数乘积为$j$的方案数,不难得到式子$f_{2i,j}=\sum\limits_{a*b\equiv j(\mod m)}f_{i,a}\times f_{i,b}$

对于乘法转加法,常见套路就是取对数。那么这里在模意义下,注意到原根$g$有很好的性质:$g^0,g^1,\cdots ,g^{m-2}$可以取遍$[1\cdots m-1]$,因此令$j\equiv g^A(\mod m)$,不妨用$A$代替$j$,以此类推。所以剩下的就是一个多项式快速幂的过程了,最终答案就是$f_x$的系数。

中途写错两个地方:为$[1\cdots m-1]$内元素按$g^i$标号时,写成遍历$[0\cdots m-1]$(这里整体下标减一。说到底还是对式子不熟练。);给$x$重标号时候,写成 if (x==tar&&!fl) tar = x, fl = ; ……

 #include<bits/stdc++.h>
#define MO 1004535809
const int maxn = ; int T,n,m,tar,len,dt,inv3,invn,ort;
int f[maxn],g[maxn],cov[maxn],tmp1[maxn],tmp2[maxn];
bool vis[maxn]; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
int qmi(int a, int b, int p)
{
int ret = ;
for (; b; b>>=, a=1ll*a*a%p)
if (b&) ret = 1ll*ret*a%p;
return ret;
}
int fndRoot()
{
int fac[], tot = , pos = m-;
for (int i=; i*i<=pos; i++)
if (pos%i==){
fac[++tot] = i;
while (pos%i==) pos /= i;
}
if (pos!=) fac[++tot] = pos;
pos = m-;
for (int i=; i<=pos; i++)
{
bool chk = true;
for (int j=; j<=tot&&chk; j++)
if (qmi(i, pos/fac[j], m)==) chk = false;
if (chk) return i;
}
return -;
}
void NTT(int *a, int opt)
{
for (int i=; i<len; i++)
if (i < cov[i]) std::swap(a[i], a[cov[i]]);
for (int i=; i<len; i<<=)
{
int Wn = qmi(, (MO-)/(i<<), MO);
if (opt==-) Wn = qmi(inv3, (MO-)/(i<<), MO);
for (int j=, p=i<<; j<len; j+=p)
{
int w = ;
for (int k=; k<i; k++, w=1ll*w*Wn%MO)
{
int valx = a[j+k], valy = 1ll*w*a[i+j+k]%MO;
a[j+k] = (valx+valy)%MO, a[i+j+k] = (valx-valy+MO)%MO;
}
}
}
if (opt==-) for (int i=; i<len; i++) a[i] = 1ll*a[i]*invn%MO;
}
void mult(int *a, int *b)
{
for (int i=; i<len; i++) tmp1[i] = a[i], tmp2[i] = b[i];
NTT(tmp1, ), NTT(tmp2, );
for (int i=; i<len; i++) tmp1[i] = 1ll*tmp1[i]*tmp2[i]%MO;
NTT(tmp1, -);
for (int i=; i<m-; i++) a[i] = (tmp1[i]+tmp1[i+m-])%MO;
}
int main()
{
T = read(), m = read(), tar = read(), n = read();
inv3 = qmi(, MO-, MO), ort = fndRoot();
for (int i=; i<=n; i++) vis[read()] = true;
for (int i=, x=, fl=; i<m-; i++, x=1ll*x*ort%m)
{
if (vis[x]) g[i] = ;
if (x==tar&&!fl) tar = i, fl = ;
}
for (len=; len<=(m-)<<; len<<=) ++dt;
for (int i=; i<len; i++)
cov[i] = (cov[i>>]>>)|((i&)<<(dt-));
f[] = , invn = qmi(len, MO-, MO);
for (; T; T>>=, mult(g, g))
if (T&) mult(f, g);
printf("%d\n",f[tar]);
return ;
}

END

【NTT】bzoj3992: [SDOI2015]序列统计的更多相关文章

  1. [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)

    3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1888  Solved: 898[Submit][Statu ...

  2. BZOJ3992: [SDOI2015]序列统计(NTT 原根 生成函数)

    题意 题目链接 给出大小为\(S\)的集合,从中选出\(N\)个数,满足他们的乘积\(\% M = X\)的方案数 Sol 神仙题Orz 首先不难列出最裸的dp方程,设\(f[i][j]\)表示选了\ ...

  3. 2018.12.31 bzoj3992: [SDOI2015]序列统计(生成函数+ntt+快速幂)

    传送门 生成函数简单题. 题意:给出一个集合A={a1,a2,...as}A=\{a_1,a_2,...a_s\}A={a1​,a2​,...as​},所有数都在[0,m−1][0,m-1][0,m− ...

  4. BZOJ3992: [SDOI2015]序列统计

    Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列. ...

  5. BZOJ3992 [SDOI2015]序列统计 【生成函数 + 多项式快速幂】

    题目 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生成了许多这样的数列.但是小C有一个问题 ...

  6. 【动态规划】bzoj3992 [Sdoi2015]序列统计 10分

    #include<cstdio> using namespace std; #define MOD 1004535809 int a[8001],f[1001][101],n,m,x,S; ...

  7. 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂

    [BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属 ...

  8. 【BZOJ3992】序列统计(动态规划,NTT)

    [BZOJ3992]序列统计(动态规划,NTT) 题面 BZOJ 题解 最裸的暴力 设\(f[i][j]\)表示前\(i\)个数,积在膜意义下是\(j\)的方案数 转移的话,每次枚举一个数,直接丢进去 ...

  9. BZOJ 3992: [SDOI2015]序列统计 NTT+快速幂

    3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1155  Solved: 532[Submit][Statu ...

随机推荐

  1. 微信授权登录(OAuth2.0)-- 随记

    1.OAuth2.0简介 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户 ...

  2. FTP原理与配置

    FTP(file transfer protocol)文件传输协议(基于tcp协议).是用来传送文件的协议,使用FTP实现文件传输的同时,还可以保证数据传输的可靠性和高效性.通过学习我们需要掌握以下两 ...

  3. POJ 2068 NIm (dp博弈,每个人都有特定的取最大值)

    题目大意: 有2n个人,从0开始编号,按编号奇偶分为两队,循环轮流取一堆有m个石子的石堆,偶数队先手,每个人至少取1个,至多取w[i]个,取走最后一个石子的队伍输.问偶数队是否能赢. 分析: 题目数据 ...

  4. CodeForces - 93B(贪心+vector<pair<int,double> >+double 的精度操作

    题目链接:http://codeforces.com/problemset/problem/93/B B. End of Exams time limit per test 1 second memo ...

  5. Linux系统的vim编辑器的配置文件的初步说明

    vim 编辑器的基本说明 vi编辑器的功能类似于Windows下的记事本,只能编辑普通文本,而vim编辑器则相当于Windows下的notepad++等高级编辑器,提升了代码开发效率. 将vi命令默认 ...

  6. Storm概念学习系列之Tuple元组(数据载体)

    不多说,直接上干货! Tuple元组 Tuple 是 Storm 的主要数据结构,并且是 Storm 中使用的最基本单元.数据模型和元组. Tuple 描述 Tuple 就是一个值列表, Tuple ...

  7. ORA-29875 出现问题解决办法

    出现问题:Underlying DBMS error [ORA-29875: 无法执行 ODCIINDEXINSERT 例行程序ORA-20085: Insert Spatial Reference ...

  8. js小数点后保留几位方法:toFixed

    (0.22223343534).toFixed(2) 结果:0.22

  9. js识别中英文字符的字节长度并进行裁切

    //调用方法,传入字符串和需要返回的字节长度即可function cutstr(str,len){ var str_length = 0; var str_len = 0; str_cut = new ...

  10. C#工程缺少IIS组件无法打开的解决办法

    作者:朱金灿 来源:http://blog.csdn.net/clever101 同事使用VS打开一个C#工程,出现下面的错误: 这个工程是C#的桌面工程,跟IIS无关,去安装IIS太麻烦了.我想到一 ...