题目: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. 移动端tap或touch类型事件的点透问题认识

    1.什么是点透? 举例说明:下图B元素是黄色方块,B元素中包含了C元素,C元素是一个a链接,本身自带click事件按,然后又一个半透明的粉色元素A遮盖在B元素上(看图中A元素是覆盖在B元素上的,不然B ...

  2. cocos2dx打飞机项目笔记四:Enemy类和EnemyLayer类

    Enemy类没什么内容,就create和init方法,根据参数来创建不同的敌机,头文件代码如下: //飞机的类型 enum planeType {smallPlane, midPlane, bigPl ...

  3. Ubuntu或Linux搭建网站环境常见问题详解

    本屌丝常见的问题已经全部记录如下,如大家有其他问题欢迎随时跟我进行交流. 1.无法进行软件源安装  提示信息:Package has no installation candidate 具体信息如下: ...

  4. springmvc文件上传的基本描述

    SpringMVC的文件上传,底层也是使用的Apache的Commons-fileupload 可以分为三步: 1.导入依赖包 <!-- 文件上传的依赖 --> <dependenc ...

  5. MySQL锁机制和PHP锁机制

    模拟准备--如何模拟高并发访问一个脚本:apache安装文件的bin/ab.exe可以模拟并发量 -c 模拟多少并发量 -n 一共请求多少次 http://请求的脚本例如:cmd: apache安装路 ...

  6. Linux之Xinetd服务介绍

    一.概念:1.独立启动的守护进程:stand-alone,每个特定服务都有单独的守护进程,这个处理单一服务的始终存在的进程就是独立启动的守护进程. 2.超级守护进程:多个服务统一由一个进程管理,该进程 ...

  7. AppDomain.CurrentDomain.BaseDirectory

    在winform中的OnPaint事件中,AppDomain.CurrentDomain.BaseDirectory得到的是下面这个路径 C:\Program Files (x86)\Microsof ...

  8. LeetCode——max-points-on-a-line

    Question Given n points on a 2D plane, find the maximum number of points that lie on the same straig ...

  9. [转载]spring security 的 logout 功能

    原文地址:security 的 logout 功能">spring security 的 logout 功能作者:sumnny 转载自:http://lengyun3566.iteye ...

  10. Log4j2的日志配置文件,log4j2.xml文件的配置(实现控制台输出,各级别分别文件输出,自动压缩等)

    <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE html PUBLIC "-//W ...