bzoj3992【SDOI2015】序列统计
3992: [SDOI2015]序列统计
Time Limit: 30 Sec Memory Limit: 128 MB
Submit: 673 Solved: 327
[Submit][Status][Discuss]
Description
Input
一行。四个整数。N、M、x、|S|,当中|S|为集合S中元素个数。
第二行,|S|个整数,表示集合S中的全部元素。
Output
一行,一个整数,表示你求出的种类数mod
1004535809的值。
Sample Input
1 2
Sample Output
HINT
Source
NTT第一题
首先能够发现1004535809=479*2^21+1,并且是一个质数,所以能够用NTT解决。
用f[i][j]表示i个数模m等于g^j的方案数(i为2的整数次幂,g为m的原根)。则f[i][j]=∑f[i/2][k]*f[i/2][j-k]。
这样就成了卷积形式,NTT搞定。
但n并不一定是2的整数次幂,这里就要用到高速幂的思想(详见代码)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 40000
#define mod 1004535809
using namespace std;
int n,m,num,s,mg,g,bit,inv;
int a[maxn],c[maxn],A[maxn],B[maxn],ind[maxn],rev[maxn];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline ll power(ll x,int y,int p)
{
ll ret=1;
for(;y;y>>=1,x=x*x%p) if (y&1) ret=ret*x%p;
return ret;
}
inline bool get_order(int x,int m)
{
int lim=sqrt(m),phi=m-1;
F(i,1,lim) if (phi%i==0)
{
if (power(x,i,m)==1){if (i!=m-1) return false;}
if (power(x,phi/i,m)==1){if (phi/i!=m-1) return false;}
}
return true;
}
inline int get_primitive_root(int x)
{
F(i,2,x) if (get_order(i,x)) return i;
}
inline void ntt(int *a,int flag)
{
F(i,0,(1<<bit)-1) if (rev[i]>i) swap(a[i],a[rev[i]]);
F(i,1,bit)
{
int y=(1ll*flag*(mod-1)/(1<<i)+mod-1)%(mod-1);
ll wn=power(g,y,mod);
for(int j=0;(j<1<<bit);j+=(1<<i))
{
ll w=1;
F(k,j,j+(1<<(i-1))-1)
{
int u=a[k],v=w*a[k+(1<<(i-1))]%mod;
a[k]=(u+v)%mod;
a[k+(1<<(i-1))]=((u-v)%mod+mod)%mod;
w=w*wn%mod;
}
}
}
if (flag<0) F(i,0,(1<<bit)-1) a[i]=1ll*a[i]*inv%mod;
}
inline void convol(int *a,int *b)
{
int len=1<<bit;
F(i,0,len-1) c[i]=b[i];
ntt(a,1);ntt(c,1);
F(i,0,len-1) a[i]=(ll)a[i]*c[i]%mod;
ntt(a,-1);
for(int i=m-1,j=0;i<len;i++,j++) a[j]=(a[j]+a[i])%mod,a[i]=0;
}
int main()
{
n=read();m=read();num=read();s=read();
F(i,1,s) a[i]=read();
mg=get_primitive_root(m);
g=get_primitive_root(mod);
int tmp=1;
F(i,0,m-2){ind[tmp]=i;tmp=tmp*mg%m;}
for(bit=0;(1<<bit)<(m-1)*2;bit++);
inv=power(1<<bit,mod-2,mod);
F(i,0,(1<<bit)-1) rev[i]=rev[i>>1]>>1|((i&1)<<(bit-1));
A[0]=1;
F(i,1,s) if (a[i]) B[ind[a[i]]]=1;
for(;n;convol(B,B),n>>=1) if (n&1) convol(A,B);
printf("%d\n",A[ind[num]]);
return 0;
}
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]序列统计
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]序列统计 【生成函数 + 多项式快速幂】
题目 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生成了许多这样的数列.但是小C有一个问题 ...
- 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂
[BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属 ...
- BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1017 Solved: 466[Submit][Statu ...
- [SDOI2015]序列统计
[SDOI2015]序列统计 标签: NTT 快速幂 Description 给你一个模m意义下的数集,需要用这个数集生成一个数列,使得这个数列在的乘积为x. 问方案数模\(1004535809\). ...
随机推荐
- onWebView检查网页中文
问题:要检查网页中的一段文本: 开始我是这样写的: private final static String SPECIFIED_TEXT = "这个是一段中文"; onWebVie ...
- CSS3快速浏览器前缀的方法
在做前端开发时,经常要在css3的属性前加上各浏览器厂商的前缀:,如 Chrome(谷歌浏览器) :-webkit- Safari(苹果浏览器) :-webkit- Firefox(火狐浏览器) :- ...
- namespace使用方法
https://blog.csdn.net/CHIERYU/article/details/50262043 参考值这文献
- ES6中的迭代器(Iterator)和生成器(Generator)(一)
用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作 ...
- Linux zip
压缩文件: zip -r res.zip [src/] [abc.txt] 解压文件: unzip res.zip -d dir_path
- 【HTML 元素】嵌入另一张HTML文档、通过插件嵌入内容、嵌入数字表现形式
1.嵌入另一张HTML文档 iframe 元素允许在现有的HTML文档中嵌入另一张文档.下面代码展示了iframe元素的用法: <!DOCTYPE html> <html lang= ...
- AngularJS, Ember.js, Backbone这类新框架与 jQuery的重要区别在哪里?
jQuery主要是用来操作DOM的,如果单单说jQuery的话就是这样一个功能,它的插件也比较多,大家也都各自专注一个功能,可以说jQuery体系是跟着前端页面从静态到动态崛起的一个产物,他的作用就是 ...
- Effective C++ 条款17
以独立语句将newed对象置入智能指针 本节我们须要学习的知识核心是注意编译器在同一语句中,调用次序具有不确定性,不同语句中,调用次序确定. 上面的话什么意思? 请看下面代码: int priorit ...
- MPTCP 理解
背景 随着技术的发展许多设备具有了多个网络接口,而TCP依然是一个单线路的协议,在TCP的通信过程中发端和收端都 不能随意变换地址.我们可以利用多个网络接口的这一特性来改善性能和有效冗余.例 ...
- 微信小程序 - 如何通过button按钮实现分享(转发)功能
小程序官方API https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/page.html#%E9%A1%B5% ...