数列长度到了109,转移矩阵边长n到了8000,除了FFT还能怎么写??!!

当然,这题由于取模,必须用NTT.

同时由于取得是乘积,所以用m的原根来搞,每次NTT完了,把后面的部分加到前面去.

注意,X不会出现0,因此一旦S集合中出现0,删掉.原根判不了0.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<iomanip>
using namespace std;
#define ll long long
#define db double
#define up(i,j,n) for(ll i=j;i<=n;i++)
#define pii pair<ll,ll>
#define uint unsigned ll
#define FILE "dealing"
ll read(){ll x=0,f=1,ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;
}
template<class T> bool cmax(T& a,T b){return a<b?a=b,true:false;}
template<class T> bool cmin(T& a,T b){return a>b?a=b,true:false;}
const ll maxn=400100,limit=128,inf=1000000000,r=3,mod=1004535809;
ll n,m,X,S,G;
ll a[maxn],b[maxn],id[maxn];
ll fast(ll a,ll b,ll mod){ll ans=1;while(b){if(b&1)ans=ans*a%mod;b>>=1;a=a*a%mod;}return ans;
}
void print(ll* a,ll len){up(i,0,len-1)printf("%lld ",a[i]);cout<<endl;
}
namespace prepare{//求M原根const ll maxn=8080;ll b[maxn],prime[maxn],tail,q[maxn],head;void getprime(){for(ll i=2;i<maxn;i++){if(!b[i])prime[++tail]=i;for(ll j=1;prime[j]*i<maxn&&j<=tail;j++){b[i*prime[j]]=1;if(i%prime[j]==0)break;}}}ll solve(ll N){getprime();ll p=N-1;N--;for(ll i=1;i<=tail;i++){if(N==1)break;if(N%prime[i]==0)q[++head]=prime[i];while(N%prime[i]==0)N/=prime[i];}for(ll i=2;i<=p;i++){bool flag=0;for(ll j=1;j<=head;j++)if(fast(i,p/(q[j]),p+1)==1)flag=1;if(!flag)return i;}return 0;}
};
namespace NTT{ll R[maxn],a[maxn],b[maxn],w[maxn];ll H,L;void NTT(ll* a,ll flag){for(ll i=0;i<L;i++)if(i<R[i])swap(a[i],a[R[i]]);for(ll len=2;len<=L;len<<=1){ll g=fast(r,(mod-1)/len,mod),l=len>>1;if(flag)g=fast(g,mod-2,mod);w[0]=1;up(i,1,l)w[i]=w[i-1]*g%mod;for(ll st=0;st<L;st+=len)for(ll k=0;k<l;k++){ll x=a[st+k],y=w[k]*a[st+k+l]%mod;a[st+k]=(x+y)%mod,a[st+k+l]=(x-y+mod)%mod;}}if(flag){ll inv=fast(L,mod-2,mod);up(i,0,L-1)a[i]=a[i]*inv%mod;}}void solve(ll* c,ll* d,ll n,ll m,ll* ch){n++,m++;up(i,0,n-1)a[i]=c[i];up(i,0,m-1)b[i]=d[i];for(H=0,L=1;L<n+m-1;H++)L<<=1;up(i,n,L)a[i]=0;up(i,m,L)b[i]=0;up(i,1,L)R[i]=(R[i>>1]>>1)|((i&1)<<(H-1));NTT(a,0);NTT(b,0);up(i,0,L-1)a[i]=a[i]*b[i]%mod;NTT(a,1);up(i,0,n+m-2)ch[i]=a[i];}
};
ll c[maxn],ans[maxn],tmp[maxn];
int main(){freopen(FILE".in","r",stdin);freopen(FILE".out","w",stdout);n=read();m=read();X=read(),S=read();up(i,1,S)a[i]=read();G=prepare::solve(m);ll w=1;up(i,0,m-1){id[w]=i;w=w*G%m;}up(i,1,S)if(a[i])a[i]=id[a[i]];X=id[X];up(i,1,S)if(a[i])c[a[i]]++;ans[0]=1;while(n){if(n&1){NTT::solve(ans,c,m,m,tmp);up(i,0,m-1)ans[i]=tmp[i];up(i,1,m)ans[i]=(ans[i]+tmp[i+m-1])%mod;}n>>=1;NTT::solve(c,c,m,m,tmp);up(i,0,m-1)c[i]=tmp[i];up(i,1,m)c[i]=(c[i]+tmp[i+m-1])%mod;}printf("%lld\n",ans[X]);return 0;
}

  

转载于:https://www.cnblogs.com/chadinblog/p/6556004.html

BZOJ 3992 [SDOI2015]序列统计相关推荐

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

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

  2. Luogu P3321 [SDOI2015]序列统计

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

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

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

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

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

  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]序列统计

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

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

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

  9. P3321 [SDOI2015]序列统计

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

最新文章

  1. 开源Linux 3.3内核首次融合Android代码
  2. [Baltic2009]Radio Transmission
  3. 你需要XXX的权限对此文件(此文件夹进行)修改
  4. 设计模式19——行为型模式之备忘录模式
  5. 公式冒号是什么意思_三角学中,这么一堆公式其实就说了2个事而已
  6. 2014年9月21日_随笔,jdic,ETL,groovy,Nutz好多东西想学
  7. 数据结构-栈3-栈的应用-就近匹配
  8. Android 系统(184)---Android APN 配置
  9. MySQL索引(如何设计索引)
  10. Tarjan算法查找强联通组件的程序
  11. 大数据如何应用在企业人力资源管理
  12. H5常用代码:适配方案5
  13. iocomp入门教程-以MFC中iplotx为例
  14. 【笑话】男生追女生的数学模型
  15. (保姆级)Oracle的下载及安装详细教程
  16. Scripting for Testers 测试人员脚本编程教程 Lynda课程中文字幕
  17. php获取当前网址附带(http://或者https//)
  18. 3D动画制作太复杂?谷歌推出MonsterMash,绘画小白都能用
  19. BouncyCastle使用注意事项
  20. iwanna用哪个计算机语言,IwannabetheCreator电脑版

热门文章

  1. ndows live id怎么登陆,手机如何注册和使用Windows Live ID帐号
  2. 查看约束信息_【华智产品汇】育种信息安全的守护者——华智育种管家
  3. 找出连续最长数字串python_字符串中找出连续最长的数字字符串的实例代码
  4. python怎么读出当前时间_Python读取Excel,日期列读出来是数字的处理
  5. java接口配置文件_Java读取property配置文件,另接口的配置
  6. win7 磁盘根目录(E盘)添加管理员权限
  7. java 内部类 线程_java多线程基本概述(十四)——Thread内部类的几种写法
  8. java bidi_Java Bidi createLineBidi()用法及代码示例
  9. android 自定义 进度条 旋转,Android_Android ProgressBar进度条使用详解,ProgressBar进度条,分为旋转进 - phpStudy...
  10. cmw500综合测试仪使用_高端示波器是德MSOX4154A示波器-产品使用操作说明书【二手示波器吧】...