板子题都差点不会了

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. JS异步解决方案之概念理解-----------阻塞和非阻塞,同步和异步,并发和并行,单线程和多线程

    首先记住一句话,JS是单线程的. 单线程意味着什么?单线程意味着 它不能依靠自己实现异步. JS实现的异步,往往都是靠 浏览器.Node 的机制(事件驱动.回调)实现的. 下面让我这个单身狗 以谈恋爱 ...

  2. Helvetic Coding Contest 2016 online mirror C2

    Description Further research on zombie thought processes yielded interesting results. As we know fro ...

  3. jquery——选项卡

    下面是闭包做选项卡: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  4. mediawiki登录时第一次会跳回登录页面,第二次才能登录成功

    原因是:LocalSetting.php中的$wgServer属性使用的是ip,改为域名后成功解决问题 补充:改为域名后使用ip访问会出现第一次登录跳回登录界面的情况,应该根据实际情况来设置$wgSe ...

  5. Regionals 2014 >> Asia - Taichung 7003 - A Balance Game on Trees 树形DP + 二维费用背包

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  6. (转)/etc/sysctl.conf 调优 & 优化Linux内核参数

    /etc/sysctl.conf 调优 & 优化Linux内核参数 from: http://apps.hi.baidu.com/share/detail/15652067 http://ke ...

  7. JAVA多线程面试题目

    1,java中有几种方法可以实现一个线程? 答:在Java中实现一个线程有两种方法,第一是实现Runnable接口实现它的run()方法,第二种是继承Thread类,覆盖它的run()方法.这两种方法 ...

  8. 双层列表 datagrid里属性

    frozenColumns: [ [{ title: "姓名"}] ], columns: [ [{"title":"延时原因"}], [{ ...

  9. easyUI 鼠标悬停某行提示

      最近参与公司的电子档案系统的开发,需求是需要用户鼠标悬停某一行时,需要根据后台业务数据进行提示. 档案系统开发采用的框架是struts2+mybatis+spring+easyUI开发,而前端的e ...

  10. SpringMVC10 InitBinder 注册自定义编辑器

    1.配置web.xml文件 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3// ...