2020省选模拟训练1 排列(perm)多项式exp+EGF
这道题真的还是简单的一批.....
我当时要是参加考试的话该多好(凭这一道题就能进前 5 了)
十分显然的指数型生成函数.
令 $f[i]$ 表示有 $i$ 个点的答案.
然后显然有 $f[i]=\sum_{j=1}^{i}\binom{i}{j} \times \frac{j!}{j} \times f[i-j]$
然后这个就是一个 EGF 的形式.
令 $A(x)$ 表示只有一个环的时候的生成函数.
然后有 $ans[i]=[x^i] \sum_{i} \frac{A^i(x)}{i!}$
故 $ans[i]=[x^i] e^{A(x)}$
code:
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <string>
#define ll long long
#define ull unsigned long long
using namespace std;
namespace IO
{
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd()
{
int x=0; char s=nc();
while(s<'0') s=nc();
while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
return x;
}
void print(int x) {if(x>=10) print(x/10);putchar(x%10+'0');}
void setIO(string s)
{
string in=s+".in";
string out=s+".out";
freopen(in.c_str(),"r",stdin);
// freopen(out.c_str(),"w",stdout);
}
};
const int G=7;
const int N=400005;
const int mod=950009857;
int A[N],B[N],w[2][N],mem[N*100],*ptr=mem,tmpa[N],tmpb[N],aa[N],bb[N];
inline int qpow(int x,int y)
{
int tmp=1;
for(;y;y>>=1,x=(ll)x*x%mod) if(y&1) tmp=(ll)tmp*x%mod;
return tmp;
}
inline int INV(int a) { return qpow(a,mod-2); }
inline void ntt_init(int len)
{
int i,j,k,mid,x,y;
w[1][0]=w[0][0]=1,x=qpow(G,(mod-1)/len),y=qpow(x,mod-2);
for (i=1;i<len;++i) w[0][i]=(ll)w[0][i-1]*x%mod,w[1][i]=(ll)w[1][i-1]*y%mod;
}
void NTT(int *a,int len,int flag)
{
int i,j,k,mid,x,y;
for(i=k=0;i<len;++i)
{
if(i>k) swap(a[i],a[k]);
for(j=len>>1;(k^=j)<j;j>>=1);
}
for(mid=1;mid<len;mid<<=1)
for(i=0;i<len;i+=mid<<1)
for(j=0;j<mid;++j)
{
x=a[i+j], y=(ll)w[flag==-1][len/(mid<<1)*j]*a[i+j+mid]%mod;
a[i+j]=(x+y)%mod;
a[i+j+mid]=(x-y+mod)%mod;
}
if(flag==-1)
{
int rev=INV(len);
for(i=0;i<len;++i) a[i]=(ll)a[i]*rev%mod;
}
}
inline void getinv(int *a,int *b,int len,int la)
{
if(len==1) { b[0]=INV(a[0]); return; }
getinv(a,b,len>>1,la);
int l=len<<1,i;
memset(A,0,l*sizeof(A[0]));
memset(B,0,l*sizeof(A[0]));
memcpy(A,a,min(la,len)*sizeof(a[0]));
memcpy(B,b,len*sizeof(b[0]));
ntt_init(l);
NTT(A,l,1),NTT(B,l,1);
for(i=0;i<l;++i) A[i]=((ll)2-(ll)A[i]*B[i]%mod+mod)*B[i]%mod;
NTT(A,l,-1);
memcpy(b,A,len<<2);
}
void get_dao(int *a,int *b,int len)
{
for(int i=1;i<len;++i) b[i-1]=(ll)i*a[i]%mod;
b[len-1]=0;
}
void get_jifen(int *a,int *b,int len)
{
for(int i=1;i<len;++i) b[i]=(ll)INV(i)*a[i-1]%mod;
b[0]=0;
}
void get_ln(int *a,int *b,int len,int la)
{
int l=len<<1,i;
memset(tmpa,0,l<<2);
memset(tmpb,0,l<<2);
get_dao(a,tmpa,min(len,la));
getinv(a,tmpb,len,la);
ntt_init(l);
NTT(tmpa,l,1),NTT(tmpb,l,1);
for(i=0;i<l;++i) tmpa[i]=(ll)tmpa[i]*tmpb[i]%mod;
NTT(tmpa,l,-1);
get_jifen(tmpa,b,len);
}
void get_exp(int *a,int *b,int len,int la)
{
if(len==1) { b[0]=1; return; }
int l=len<<1,i;
get_exp(a,b,len>>1,la);
for(i=0;i<l;++i) aa[i]=bb[i]=0;
for(i=0;i<(len>>1);++i) aa[i]=b[i];
get_ln(b,bb,len,len>>1);
for(i=0;i<len;++i) bb[i]=(ll)(mod-bb[i]+(i>=la?0:a[i]))%mod;
bb[0]=(bb[0]+1)%mod;
ntt_init(l);
NTT(aa,l,1),NTT(bb,l,1);
for(i=0;i<l;++i) aa[i]=(ll)aa[i]*bb[i]%mod;
NTT(aa,l,-1);
for(i=0;i<len;++i) b[i]=aa[i];
}
struct poly
{
int len,*a;
poly(){}
poly(int l) {len=l,a=ptr,ptr+=l; }
inline void rev() { reverse(a,a+len); }
inline void fix(int l) {len=l,a=ptr,ptr+=l;}
inline void get_mod(int l) { for(int i=l;i<len;++i) a[i]=0; len=l; }
inline poly dao()
{
poly re(len-1);
for(int i=1;i<len;++i) re.a[i-1]=(ll)i*a[i]%mod;
return re;
}
inline poly jifen()
{
poly c;
c.fix(len+1);
c.a[0]=0;
for(int i=1;i<=len;++i) c.a[i]=(ll)a[i-1]*INV(i)%mod;
return c;
}
inline poly Inv(int l)
{
int lim=1;
while(lim<=l) lim<<=1;
poly b(lim);
getinv(a,b.a,lim,len);
b.get_mod(l);
return b;
}
inline poly ln(int l)
{
int lim=1;
while(lim<=l) lim<<=1;
poly b(lim);
get_ln(a,b.a,lim,len);
return b;
}
inline poly exp(int l)
{
int lim=1;
while(lim<=l) lim<<=1;
poly b(lim);
get_exp(a,b.a,lim,len);
return b;
}
inline poly q_pow(int k,int l)
{
int lim=1;
while(lim<=l) lim<<=1;
poly b(lim),c(lim);
get_ln(a,b.a,lim,len);
for(int i=0;i<b.len;++i) b.a[i]=(ll)b.a[i]*k%mod;
get_exp(b.a,c.a,lim,b.len);
c.get_mod(l);
return c;
}
inline poly operator*(const poly &b) const
{
poly c(len+b.len-1);
if(c.len<=500)
{
for(int i=0;i<len;++i)
if(a[i]) for(int j=0;j<b.len;++j) c.a[i+j]=(c.a[i+j]+(ll)(a[i])*b.a[j])%mod;
return c;
}
int n=1;
while(n<(len+b.len)) n<<=1;
memset(A,0,n<<2);
memset(B,0,n<<2);
memcpy(A,a,len<<2);
memcpy(B,b.a,b.len<<2);
ntt_init(n);
NTT(A,n,1), NTT(B,n,1);
for(int i=0;i<n;++i) A[i]=(ll)A[i]*B[i]%mod;
NTT(A,n,-1);
memcpy(c.a,A,c.len<<2);
return c;
}
poly operator+(const poly &b) const
{
poly c(max(len,b.len));
for(int i=0;i<c.len;++i) c.a[i]=((i<len?a[i]:0)+(i<b.len?b.a[i]:0))%mod;
return c;
}
poly operator-(const poly &b) const
{
poly c(len);
for(int i=0;i<len;++i)
{
if(i>=b.len) c.a[i]=a[i];
else c.a[i]=(a[i]-b.a[i]+mod)%mod;
}
return c;
}
poly operator/(poly u)
{
int n=len,m=u.len,l=1;
while(l<(n-m+1)) l<<=1;
rev(),u.rev();
poly v=u.Inv(l);
v.get_mod(n-m+1);
poly re=(*this)*v;
rev(),u.rev();
re.get_mod(n-m+1);
re.rev();
return re;
}
poly operator%(poly u)
{
poly re=(*this)-u*(*this/u);
re.get_mod(u.len-1);
return re;
}
};
#define MAX 400003
int fac[N],in[N],g[N],bu[N];
void init()
{
int i,j;
fac[0]=in[0]=1;
for(i=1;i<MAX;++i) fac[i]=(ll)i*fac[i-1]%mod,in[i]=INV(i);
}
int main()
{
// IO::setIO("input");
int i,j,n,k;
init();
scanf("%d%d",&n,&k);
for(i=1;i<=k;++i)
{
int x;
scanf("%d",&x),bu[x]=1;
}
poly A(n+1);
for(i=0;i<=n;++i) if(bu[i]) A.a[i]=in[i];else A.a[i]=0;
poly re=A.exp(n+1);
for(i=1;i<=n;++i) printf("%d\n",(ll)fac[i]*re.a[i]%mod);
return 0;
}
2020省选模拟训练1 排列(perm)多项式exp+EGF的更多相关文章
- BZOJ 1072: [SCOI2007]排列perm 状态压缩DP
1072: [SCOI2007]排列perm Description 给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0).例如123434有90种排列能被2整除,其中末位为 ...
- SCOI2007排列perm
1072: [SCOI2007]排列perm Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 805 Solved: 497[Submit][Stat ...
- BZOJ 1072 [SCOI2007]排列perm
1072: [SCOI2007]排列perm Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1268 Solved: 782[Submit][Sta ...
- 【BZOJ】【1072】【SCOI2007】排列perm
暴力 ……傻逼题我还WA了这么多次(有几次是忘了删调试信息……sigh) 直接统计0~9各有多少个,枚举数字就行了……因为是直接枚举的数字,而不是枚举用了s中的哪一位,所以是不用去重的!(我一开始写的 ...
- 【BZOJ】4555: [Tjoi2016&Heoi2016]求和 排列组合+多项式求逆 或 斯特林数+NTT
[题意]给定n,求Σi=0~nΣj=1~i s(i,j)*2^j*j!,n<=10^5. [算法]生成函数+排列组合+多项式求逆 [题解]参考: [BZOJ4555][Tjoi2016& ...
- [BZOJ1072][SCOI2007]排列perm 状压dp
1072: [SCOI2007]排列perm Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2488 Solved: 1546[Submit][St ...
- bzoj1072【SCOI2007】排列perm
1072: [SCOI2007]排列perm Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1479 Solved: 928 [id=1072&q ...
- 【WC2019】数树 树形DP 多项式exp
题目大意 有两棵 \(n\) 个点的树 \(T_1\) 和 \(T_2\). 你要给每个点一个权值吗,要求每个点的权值为 \([1,y]\) 内的整数. 对于一条同时出现在两棵树上的边,这条边的两个端 ...
- 【NOI2019模拟2019.6.27】B (生成函数+整数划分dp|多项式exp)
Description: \(1<=n,k<=1e5,mod~1e9+7\) 题解: 考虑最经典的排列dp,每次插入第\(i\)大的数,那么可以增加的逆序对个数是\(0-i-1\). 不难 ...
随机推荐
- Codeforces 1087B Div Times Mod(数学+暴力)
题意: 求(x div k) * (x mod k) = n的最小解x,保证有解 1<=n<=1e6, k<=1000,1s 思路: 注意到k的范围是1e3, 1<=x mod ...
- JS中map与forEach的区别
很多同学可能对于map与forEach的区别不是太了解,今天我们介绍一下JS中的map与forEach方法, 我对map的理解是,这个方法对一个数组arr1中的每一个元素进行遍历(传递给一个数组,参数 ...
- 动态主机配置协议-DHCP
一.DHCP 概述 当局域网中有大量的PC时.如果我们逐个为每台PC去手动配置IP.那这就是一个吃力也未必讨好的办法 累死你 而DHCP 刚好可以解决这个问题.DHCP全称(动态主机配置协议).使用的 ...
- 使用ASDM 管理 ciscoASA设备
用vm虚拟机模拟了一台 ASA设备 自适应安全设备软件为 ASA8.25 asdm镜像为asdm-6.49.bin 用客户端连接时,一定要安装java jre,版本我是用的是7,6应该也可以. ...
- HDU 1006 模拟
Tick and Tick Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
- window下建立vue.js项目
安装node.js 直接下载安装文件安装就可以了 vue项目搭建 .到自己要件项目的文件夹运行cmd命令 .如果没有安装vue-cli .npm install -g vue-cli .vue ini ...
- 自己用C语言写RH850 F1L serial bootloader
了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 由于有了RH850 F ...
- Chrome Vue Devtools插件安装和使用
安装:fq后在chrome应用商店搜索 Vue Devtools并安装,安装成功后浏览器右上角有vue的图标 安装完毕后,打开含有vue框架的网站,这是vue图标会变亮,进入开发者工具,再右侧vue选 ...
- C#设计模式学习笔记:(11)享元模式
本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7792973.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲结构型设计模式的第六个模式--享 ...
- CSS中元素的显示模式
在CSS中,根据元素显示模式的不同元素标签被分为了两类:行内元素(inline-level).块级元素(block-level). 1,首先介绍什么是行内元素,什么又是块级元素? 1.1,行内元素就 ...