BZOJ3992:[SDOI2015]序列统计——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3992
https://www.luogu.org/problemnew/show/P3321
小C有一个集合S,里面的元素都是小于M的非负整数。他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S。小C用这个生成器生成了许多这样的数列。但是小C有一个问题需要你的帮助:给定整数x,求所有可以生成出的,且满足数列中所有数的乘积mod M的值等于x的不同的数列的有多少个。小C认为,两个数列{Ai}和{Bi}不同,当且仅当至少存在一个整数i,满足Ai≠Bi。另外,小C认为这个问题的答案可能很大,因此他只需要你帮助他求出答案mod 1004535809的值就可以了。
参考:http://www.cnblogs.com/candy99/p/6391483.html
打眼一看模数就是一个原根为3的MTT质数,先敲(抄)为敬。
然后求方案,美滋滋生成函数求完之后n次幂。
emmm然而生成函数只能做加法不能乘啊怎么办?
我们可以把乘法换成加法啊!
曾经做过一道题,把所有数取log……emmm这题显然不行。
(瞄了眼题解……
哇用原根表示数,这样乘法就表示成了指数之间的加法真是非常妙啊!
(当然注意对指数要对m-1取模才行)
#include<cstdio>
#include<cctype>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const ll P=;
const int G=;
const int N=3e4+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
ll qpow(ll a,ll n,ll p){
ll res=;
while(n){
if(n&)res=res*a%p;
a=a*a%p;n>>=;
}
return res;
}
void MTT(ll a[],int n,int on){
for(int i=,j=n>>;i<n-;i++){
if(i<j)swap(a[i],a[j]);
int k=n>>;
while(j>=k){j-=k;k>>=;}
if(j<k)j+=k;
}
for(int i=;i<=n;i<<=){
ll res=qpow(G,(P-)/i,P);
for(int j=;j<n;j+=i){
ll w=;
for(int k=j;k<j+i/;k++){
ll u=a[k],t=w*a[k+i/]%P;
a[k]=(u+t)%P;
a[k+i/]=(u-t+P)%P;
w=w*res%P;
}
}
}
if(on==-){
ll inv=qpow(n,P-,P);
a[]=a[]*inv%P;
for(int i=;i<=n/;i++){
a[i]=a[i]*inv%P;
if(i!=n-i)a[n-i]=a[n-i]*inv%P;
swap(a[i],a[n-i]);
}
}
}
vector<int>v;
bool pan(int g,int p){
for(int i=;i<v.size();i++){
if(qpow(g,(p-)/v[i],p)==)return ;
}
return ;
}
int primitive(int p){
int res=p-;v.clear();
for(int i=;i*i<=res;i++){
if(res%i==){
v.push_back(i);
while(res%i==)res/=i;
}
}
if(res!=)v.push_back(res);
for(int i=;;i++){
if(pan(i,p))return i;
}
}
int nn,n,m,x,s,sum,ind[N];
void multi(ll a[],ll b[]){
static ll c[N];
for(int i=;i<nn;i++)c[i]=b[i];
MTT(a,nn,);MTT(c,nn,);
for(int i=;i<nn;i++)a[i]=a[i]*c[i]%P;
MTT(a,nn,-);
for(int i=;i<m-;i++)
a[i]=(a[i]+a[i+m-])%P,a[i+m-]=;
}
void sqr(ll a[]){
MTT(a,nn,);
for(int i=;i<nn;i++)a[i]=a[i]*a[i]%P;
MTT(a,nn,-);
for(int i=;i<m-;i++)
a[i]=(a[i]+a[i+m-])%P,a[i+m-]=;
}
ll a[N],ans[N];
int main(){
n=read(),m=read(),x=read(),s=read();
int g=primitive(m),k=;
for(int i=;i<m-;i++){
ind[k]=i;k=k*g%m;
}
for(int i=;i<=s;i++){
int w=read();
if(w)a[ind[w]]=;
}
nn=;ans[]=;
while(nn<*m)nn<<=;
while(n){
if(n&)multi(ans,a);
sqr(a);n>>=;
}
printf("%lld\n",ans[ind[x]]);
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +
+++++++++++++++++++++++++++++++++++++++++++
BZOJ3992:[SDOI2015]序列统计——题解的更多相关文章
- [BZOJ3992][SDOI2015]序列统计(DP+原根+NTT)
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1888 Solved: 898[Submit][Statu ...
- BZOJ3992: [SDOI2015]序列统计(NTT 原根 生成函数)
题意 题目链接 给出大小为\(S\)的集合,从中选出\(N\)个数,满足他们的乘积\(\% M = X\)的方案数 Sol 神仙题Orz 首先不难列出最裸的dp方程,设\(f[i][j]\)表示选了\ ...
- BZOJ3992 [SDOI2015]序列统计 【生成函数 + 多项式快速幂】
题目 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生成了许多这样的数列.但是小C有一个问题 ...
- BZOJ3992: [SDOI2015]序列统计
Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列. ...
- 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− ...
- 【动态规划】bzoj3992 [Sdoi2015]序列统计 10分
#include<cstdio> using namespace std; #define MOD 1004535809 int a[8001],f[1001][101],n,m,x,S; ...
- 【NTT】bzoj3992: [SDOI2015]序列统计
板子题都差点不会了 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生 ...
- 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂
[BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属 ...
- 【题解】SDOI2015序列统计
[题解]SDOI2015序列统计 来自永不AFO的YYB的推荐 这里是乘积,比较麻烦,不过由于给定的序列膜数是个小质数,所以可以\(O(m^2\log m)\)找原跟(实际上不需要这么多). 乘积有点 ...
随机推荐
- android学习十三 首选项
1,首选项可用用来持久保存用户设置,游戏最高分等 2,首选项有,列表首选项,复选框首选项,对话框首选项.. 3,通过xml文件和代码创建首选项 addPreferencesFromResou ...
- python 函数定义顺序
#!/usr/bin/python # Hello World def order(): print("haha") print('Hello World!') order()
- node-redis使用记录
redis的高速存取性能让人印象深刻,虽然是分布式存储,但相比本地内存,性能毫不逊色. 之所以能做到这点,是由于redis的“单线程,多路复用IO”,同一时刻只有一个操作在进行. 而且多次建立从red ...
- 软件测试工程师必备的SQL语句基础
为一个软件测试工程师,我们在测试过程中往往需要对数据库数据进行操作,但是我们的操作大多以查询居多,有时会涉及到新增,修改,删除等操作,所以我们其实并不需要对数据库的操作有特别深入的了解,以下是我在工作 ...
- MySQL☞自连接
自连接:一张表中根据自身列之间的关联关系,自己跟自己链接. A.创建一个user表,且插入数据,数据如下: B.分析: 把user表看成两张表,一张员工表,一张领导表,发现员工表中lead(领导编号) ...
- Iview 表单提交: Cannot read property 'validate' of undefined
提交表单时,提示报这个错,找了半天,然后也百度了很久,一直没找到答案,代码如下: <link href="~/lib/iview3.1.4/styles/iview.css" ...
- NGUI组件整理总结
一图流: 注意: private void RClickUI(Vector3 newPos) { this.gameObject.SetActive(true); this.transform.loc ...
- ORACLE高级部分内容
1.pl/sql基本语句 DECLARE BEGIN END; / 循环语句 DECLARE I NUMBER(2):=1; BEGIN WHILE I<100 LOOP I:=I+1; EN ...
- [2018 ACL Short and System] 对话系统
Short Paper(s) 1. Task-oriented Dialogue System for Automatic Diagnosis. (Cited by 0) Zhongyu Wei, ...
- oracle常用函数总结
Oracle常用函数总结 ---oracle常用函数-----一.数值型常用函数----取整数--select floor(10.1) from dual;--将n四舍五入,保留小数点后m位(默认情况 ...