[SDOI2015]序列统计

题目描述

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

输入输出格式

输入格式:

一行,四个整数,\(N、M、x、|S|\),其中\(|S|\)为集合S中元素个数。第二行,\(|S|\)个整数,表示集合\(S\)中的所有元素。

输出格式:

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

输入输出样例

输入样例#1:

复制

4 3 1 2
1 2

输出样例#1:

复制

8

说明

【样例说明】

可以生成的满足要求的不同的数列有(1,1,1,1)、(1,1,2,2)、(1,2,1,2)、(1,2,2,1)、(2,1,1,2)、(2,1,2,1)、(2,2,1,1)、(2,2,2,2)。

【数据规模和约定】

对于10%的数据,\(1\le N\le 1000\);

对于30%的数据,\(3\le M\le 100\);

对于60%的数据,\(3\le M\le 800\);

对于全部的数据,\(1\le N\le 10^9,3\le M\le 8000,M为质数,1\le x\le M-1\),输入数据保证集合\(S\)中元素不重复

我们构造函数\(A(x)=\sum_{i}[i\in S]x^i\),答案就是\(A\)自卷\(N\)次过后第\(x\)项的系数。

不过这个卷积不太寻常:\(\displaystyle c(x)=\sum_{i=1}^M\sum_{j=1}^M[i*j\% M==x]\cdot a(i)\cdot b(j)\)。

除法非常难处理,于是我们考虑转化为我们熟悉的加法。将乘法转化为加法,很容易就想到质数函数。我们设幂为\(g\),则\(g^{a*b}=g^a+g^b\)。我们对于没个数\(i\),我们取\(x\)为它的代表元,满足\(g^x\%M==i\)。

考虑选取原根\(g\),因为\(g^x\)在\(x\in[1,M-1]\)时两两不同。

于是我们将0舍去,然后就可以将乘法卷积转化为加法卷积了。具体实现要用到快速幂,每次卷积一次后,要将下标\(x\ge M-1\)的部分的值累加在\(x-(M-1)\)下标的位置上。

代码:

#include<bits/stdc++.h>
#define ll long long
#define MAXM 8005
#define mod 1004535809
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}int n,m,x,num;
ll ksm(ll t,ll x,ll M) {ll ans=1;for(;x;x>>=1,t=t*t%M)if(x&1) ans=ans*t%M;return ans;
}ll Find(ll m) {if(m==2) return 1;for(int i=2;i<=m-1;i++) {int flag=1;for(int j=2;j*j<m;j++) {if(ksm(i,(m-1)/j,m)==1) {flag=0;break;}}if(flag==1) return i;}
}int id[MAXM];
int rev[MAXM<<2];
void NTT(ll *a,int d,int flag) {static const ll G=3;int n=1<<d;for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<d-1);for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);for(int s=1;s<=d;s++) {int len=1<<s,mid=len>>1;ll w=flag==1?ksm(G,(mod-1)/len,mod):ksm(G,mod-1-(mod-1)/len,mod);for(int i=0;i<n;i+=len) {ll t=1;for(int j=0;j<mid;j++,t=t*w%mod) {ll u=a[i+j];ll v=t*a[i+j+mid]%mod;a[i+j]=(u+v)%mod;a[i+j+mid]=(u-v+mod)%mod;}}}if(flag==-1) {ll inv=ksm(n,mod-2,mod);for(int i=0;i<n;i++) a[i]=a[i]*inv%mod;}
}ll a[MAXM<<2];
ll f[MAXM<<2],ans[MAXM<<2];
void mul(ll *a,ll *b,int d) {for(int i=0;i<(1<<d);i++) a[i]=a[i]*b[i]%mod;NTT(a,d,-1);for(int i=0;i<m-1;i++) (a[i]+=a[i+m-1])%=mod,a[i+m-1]=0;
}void ksm(int k) {ans[0]=1;int d=ceil(log2(m*2));for(;k;k>>=1) {if(k&1) {NTT(ans,d,1),NTT(f,d,1);mul(ans,f,d);NTT(f,d,-1);}NTT(f,d,1);mul(f,f,d);}
}int main() {n=Get(),m=Get(),x=Get(),num=Get();ll g=Find(m);ll now=1;for(int i=0;i<m-1;i++) {id[now]=i;now=now*g%m;}int a;for(int i=1;i<=num;i++) {a=Get();if(a) f[id[a]]=1;}ksm(n);cout<<ans[id[x]];return 0;
}

转载于:https://www.cnblogs.com/hchhch233/p/10048336.html

Luogu P3321 [SDOI2015]序列统计相关推荐

  1. P3321 [SDOI2015]序列统计(离散对数下NTT,乘法换加法)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Weblink https://www.luogu.com.cn/problem/P3321 Prob ...

  2. 洛谷 - P3321 [SDOI2015]序列统计(原根+NTT)

    题目链接:点击查看 题目大意:给出一个集合 SSS,集合中的数是 [0,m)[0,m)[0,m) 且互不相同的,问从集合中选 nnn 次数字,且乘积对 mmm 取模后等于 xxx 的方案数有多少 题目 ...

  3. P3321 [SDOI2015]序列统计(未解决)

    P3321 [SDOI2015]序列统计 题意: 题解: 参考题解: 题解 P3321 [[SDOI2015]序列统计] [LG3321][SDOI2015]序列统计 神仙题..学透再补 代码:

  4. P3321 [SDOI2015]序列统计

    思路 首先有个挺显然的DP \[ dp[i][(j*k)\%m]+=dp[i-1][j]\times dp[i-1][k] \] 想办法优化这个DP 这个dp也可以写成这样 \[ dp[i][j]=\ ...

  5. [SDOI2015]序列统计

    [SDOI2015]序列统计 很有趣的一道题目,很巧妙. 显然是一个dp,考虑最朴素的dp,f[i][j]表示选i个乘起来,%m为j的方案数为多少.转移也很简单. 然而乘法的转移并不能进行什么优化,于 ...

  6. 算法学习FFT系列(2):快速数论变换NTT bzoj3992: [SDOI2015]序列统计例题详解

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

  7. BZOJ3992:[SDOI2015]序列统计——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3992 https://www.luogu.org/problemnew/show/P3321 小C ...

  8. BZOJ3992[SDOI2015]序列统计

    题目链接 洛谷 BZOJ 解析 头一回知道原根还可以这么考-- 不难想到递推的做法\(dp[i][j]\)表示长度为\(i\),乘积为\(j\)的答案,那么\(dp[i][j \cdot a[i] \ ...

  9. BZOJ 3992 [SDOI2015]序列统计

    数列长度到了109,转移矩阵边长n到了8000,除了FFT还能怎么写??!! 当然,这题由于取模,必须用NTT. 同时由于取得是乘积,所以用m的原根来搞,每次NTT完了,把后面的部分加到前面去. 注意 ...

最新文章

  1. Pycharm的运行和简单调试
  2. 筛指定区间的素数[区间偏移二次筛法]
  3. java_ant详解(转载)
  4. Netty详解(六):Netty 编解码技术
  5. getline读取不等待输入的问题
  6. ftp列表错误,flashfxp列表错误,ftp无法列目录的解决方法
  7. n个整数,其中有两个数是重复的,要求找出这两个重复的整数
  8. 基于Bmob从零开始写一个博客小程序
  9. 【转】【经典算法】——KMP,深入讲解next数组的求解
  10. java list 转json 字符串_fastjson将java list转为json字符串
  11. java面试题关于servlet_关于Java servlet的面试题目
  12. 如何打开屏幕坏的手机_手机屏幕碎了怎么开usb?不通过屏幕打开usb调试方法
  13. 二叉树的递归与非递归遍历详解
  14. Java实现冒泡排序(详解)
  15. MySQL - 唯一索引
  16. Linux文件压缩命令
  17. 自动修改文章的软件-自动修改文案原创软件
  18. Python-小游戏-乌龟吃鱼
  19. 尼康d850相机参数测试软件,新功能介绍二:景深合成与自动调焦_尼康 D850_数码影像评测-中关村在线...
  20. Assembly 调用的目标发生了异常

热门文章

  1. 通用后台管理系统(ExtJS 4.2 + Spring MVC 3.2 + Hibernate)
  2. 国际农产品交易模式 东亚模式对话国际农民丰收节贸易会
  3. 农业展会谋定丰收精髓-李加映:中国农民丰收节交易会
  4. 经济和信息化谋定研究-左晓栋:国家网络安全事件应急预案
  5. Pipenv: Python包管理神器
  6. Vuejs发送Ajax请求
  7. 对象的克隆(clone方法)
  8. as_matrix、保存训练模型
  9. Python_summary
  10. 查看mysql 默认端口号和修改端口号