题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992

有转移次数、模M余数、方案数三个值,一看就是系数的地方放一个值、指数的地方放一个值、做卷积的次数表示一个值(应该是表示转移次数)。

可以余数和方案数都要求相乘,指数只能相加,怎么办?

然后看题解,原来可以用M的原根的幂来表示余数那个信息!因为原根的几次幂和%M剩余类可以一一对应(除了%M==0!!!),所以用原根的幂表示%M余几,两个余数相乘就变成原根的指数相加了!把该余数对应的原根的指数放在多项式指数的位置,就可以NTT啦!

原根是 1~P-1 次幂的值%P各不相同的,所以可以用 0次项~M-2次项 或者 1次项~M-1 次项来表示。

n的范围要求快速幂。但不是把点值拿出来之后对点值快速幂一番再用点值还原回系数,因为每次卷积那个多项式的长度都要翻倍,所以最后n个点的个数就不够了。

所以要快速幂中每次卷积了一下后把它翻倍的长度手动循环一番变回原长M。这样就行啦!

注意数据范围!!!求的那个 x 不能为0,而给出的元素可以为0!而原根的那些幂都不会为0!(仔细一想,只有0或M的倍数才会%M==0)考虑到那个 x 不会为0、而数列中放入一个0的话值就变成0了,所以给出0以后要认为没有那个元素!!!!!

快速幂时,ans的初值应该像1一样;也就是一个多项式卷积它之后还是该多项式本身。想一想,就是在0次项赋1、其他项赋0即可。

发现>(M<<1)的项的值一定是0;所以循环的时候可以直接减掉1个(M-1)而不用模什么的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=; const ll mod=;
int n,m,M,pn,s[N],zb[N],pri[N],len,r[N<<];
int a[N<<],ans[N<<];
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='') ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return fx?ret:-ret;
}
void upd(int &x,int md){x>=md?x-=md:;}
int pw(int x,int k,int md)
{int ret=;while(k){if(k&)ret=(ll)ret*x%md;x=(ll)x*x%md;k>>=;}return ret;}
int gtrt()
{
int k=M-,tot=;
for(int i=;i*i<=k;i++)
if(k%i==){pri[++tot]=i;while(k%i==)k/=i;}
if(k>)pri[++tot]=k;
for(int g=;;g++)
{
int i;
for(i=;i<=tot;i++)
if(pw(g,(M-)/pri[i],M)==)break;
if(i>tot)return g;
}
}
void ntt(int *a,bool fx)
{
for(int i=;i<len;i++)
if(i<r[i])swap(a[i],a[r[i]]);
for(int R=;R<=len;R<<=)
{
int m=R>>;
int Wn=pw(,(mod-)/R,mod);
fx?Wn=pw(Wn,mod-,mod):;
for(int i=;i<len;i+=R)
for(int j=,w=;j<m;j++,w=(ll)w*Wn%mod)
{
int tmp=(ll)w*a[i+m+j]%mod;
a[i+m+j]=a[i+j]+mod-tmp; upd(a[i+m+j],mod);
a[i+j]=a[i+j]+tmp; upd(a[i+j],mod);
}
}
if(!fx)return; int inv=pw(len,mod-,mod);
for(int i=;i<len;i++)a[i]=(ll)a[i]*inv%mod;
}
int main()
{
n=rdn(); M=rdn(); pn=rdn(); m=rdn();
for(int i=;i<=m;i++)s[i]=rdn();
int rt=gtrt();
for(int i=,k=rt;i<M;i++,k=k*rt%M) zb[k]=i;
len=;
for(;len<=M<<;len<<=);
for(int i=;i<len;i++)r[i]=(r[i>>]>>)+((i&)?len>>:); for(int i=;i<=m;i++)if(s[i])a[zb[s[i]]]=;////if
ans[]=;///
while(n)
{
ntt(a,);
if(n&)
{
ntt(ans,);
for(int i=;i<len;i++)ans[i]=(ll)ans[i]*a[i]%mod;
ntt(ans,);
for(int i=;i<M;i++)//pos which >(M<<1) surely have no value
ans[i]+=ans[i+M-],ans[i+M-]=,upd(ans[i],mod);
}
for(int i=;i<len;i++)a[i]=(ll)a[i]*a[i]%mod;
ntt(a,);
for(int i=;i<M;i++)
a[i]+=a[i+M-],a[i+M-]=,upd(a[i],mod);
n>>=;
}
printf("%d\n",ans[zb[pn]]);
return ;
}

bzoj 3992 [SDOI2015]序列统计——NTT(循环卷积&&快速幂)的更多相关文章

  1. bzoj 3992 [SDOI2015] 序列统计 —— NTT (循环卷积+快速幂)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992 (学习NTT:https://riteme.github.io/blog/2016-8 ...

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

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

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

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

  4. bzoj 3992: [SDOI2015]序列统计 NTT+原根

    今天开始学习丧心病狂的多项式qaq......    . code: #include <bits/stdc++.h> #define ll long long #define setIO ...

  5. BZOJ 3992: [SDOI2015]序列统计 快速幂+NTT(离散对数下)

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

  6. BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]

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

  7. [BZOJ 3992][SDOI2015]序列统计

    3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 2275  Solved: 1090[Submit][Stat ...

  8. bzoj 3992: [SDOI2015]序列统计【原根+生成函数+NTT+快速幂】

    还是没有理解透原根--题目提示其实挺明显的,M是质数,然后1<=x<=M-1 这种计数就容易想到生成函数,但是生成函数是加法,而这里是乘法,所以要想办法变成加法 首先因为0和任何数乘都是0 ...

  9. BZOJ.3992.[SDOI2015]序列统计(DP NTT 原根)

    题目链接 \(Description\) 给定\(n,m,x\)和集合\(S\).求\(\prod_{i=1}^na_i\equiv x\ (mod\ m)\)的方案数.其中\(a_i\in S\). ...

随机推荐

  1. 树莓派打造对话机器人 Python(转)

    工具列表 1. **树莓派**(型号不要求,本人使用的是3B) 2. **usb麦克风**(某宝有卖,我就不打广告了) 用来录音 3. **音响或者喇叭**(某宝也有卖) 用来播放 以上就是需要的工具 ...

  2. js怎么将光标移动特定的位置:

    第一种方法: a 标签的锚: 将a标签的herf='#element_id_name'  即可 <a href="#comment_content" class=" ...

  3. DNS 主从同步配置

    DNS 主从同步配置 主从同步:主每次修改配置文件需要修改一下序列号,主从同步主要 看序列号. 从DNS:从是可以单独修改,主从不会报错.但从修改后,主端同步给从后 从端修改数据会丢失 主从原理:从会 ...

  4. post请求和get请求content_type的种类

    get请求的headers中没有content-type这个字段,post 的 content-type 有两种 : application/x-www-form-urlencoded 这种就是一般的 ...

  5. leetcode刷题2:两数相加add_two_numbers

    题目:两数相加 (难度:中等) 给定两个非空链表来表示两个非负整数.位数按照逆序方式存储,它们的每个节点只存储单个数字. 将两数相加返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以 ...

  6. 计数排序(COUNTING-SORTING)

    计数排序的思想: 计数排序是对每一个输入元素x;确定小于x的元素个数. 计数排序算法: 第一个for循环为统计arra 中的每一个数值的个数,并且放在相应arrc 数组中的arra[i]位,第二个fo ...

  7. Javascript中一些常用的宽与高

    在使用javascript制作一些网络特效时,往往要根据显示网页的显示器的一些参数展开进行.所以一些关于显示器的参数如何得到显得十分重要.下面是一些常用的显示器参数,不妨好好记一下吧! 网页可见区域宽 ...

  8. mysql启动报can't create/write to file 'var/run/mysqld/mysqld.pid 错误解决办法

    msql启动报错,启动不了. 进入mysql日志默认的路径为 /var/log/mysqld.log 查看日志,发现报错信息如下: can't create/write to file 'var/ru ...

  9. 关于Json如何转换成对象及获值问题!

    var result = eval('('+result+')'); result为Json 转换成var result对象,可以 if(result.success){ window.locatio ...

  10. 解决maven寻找依赖关系失败的问题

    在mac中会碰到依赖jdk自带的jar包而maven找不到的问题 解决方案:安装jdk中的tools到本地mvn库 mvn install:install-file -Dfile=${JAVA_HOM ...