codeforces #568B Symmetric and Transitive 快速傅里叶变换
来源:互联网 发布:药品说明书查询软件 编辑:程序博客网 时间:2024/06/11 00:19
题目大意:给定
一组二元关系满足条件等价于存在一个点使其不在任何一个二元关系中
考虑将点划分成一些集合,那么大小为
构造指数级生成函数
那么划分方案的指数级生成函数就是
但是这样不对,因为一些方案可能不包含单点
因此我们减掉不包含单点的方案数
答案函数为
取
然后……然后我就作死去写了一发FFT mod any prime!
这玩应难写得我要吐了!
4000的数据本机跑了1.7s+!1.7s+!这是
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 9000#define MOD 1000000007using namespace std;const int P[3]={998244353,1005060097,950009857};const int G[3]={3,5,7};int n,m;long long inv[M];void Pretreatment(){ int i; for(inv[1]=1,i=2;i<M;i++) inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;}struct Int_128{ unsigned long long a,b; Int_128(long long x) { a=0,b=x; } friend bool operator < (Int_128 x,Int_128 y) { return x.a < y.a || x.a == y.a && x.b < y.b ; } friend Int_128 operator + (Int_128 x,Int_128 y) { Int_128 re(0); re.a=x.a+y.a+(x.b+y.b<x.b); re.b=x.b+y.b; return re; } friend Int_128 operator - (Int_128 x,Int_128 y) { y.a=~y.a;y.b=~y.b; return x+y+1; } void Div2() { b>>=1;b|=(a&1ll)<<63;a>>=1; } friend Int_128 operator * (Int_128 x,Int_128 y) { Int_128 re=0; while(y.a || y.b) { if(y.b&1) re=re+x; x=x+x; y.Div2(); } return re; } friend Int_128 operator % (Int_128 x,Int_128 y) { Int_128 temp=y; int cnt=0; while(temp<x) temp=temp+temp,++cnt; for(;cnt>=0;cnt--) { if(temp<x) x=x-temp; temp.Div2(); } return x; }};long long Quick_Power(long long x,int y,int P){ long long re=1; while(y) { if(y&1) (re*=x)%=P; (x*=x)%=P; y>>=1; } return re;}void FFT(int a[],int n,int type,int P,int G){ static int rev_bit[M]; int i,j,k,bit; long long w,wn; for(bit=0;(1<<bit)!=n;bit++); for(i=0;i<n;i++) rev_bit[i]=(rev_bit[i>>1]>>1)|((i&1)<<bit-1); for(i=0;i<n;i++) if(i<rev_bit[i]) swap(a[i],a[rev_bit[i]]); for(k=2;k<=n;k<<=1) for(wn=Quick_Power(G,(long long)(P-1)/k*type%(P-1),P),j=0;j<n;j+=k) for(w=1,i=0;i<k>>1;i++,(w*=wn)%=P) { long long temp1=a[i+j],temp2=a[i+j+(k>>1)]; a[i+j]=(temp1+w*temp2)%P; a[i+j+(k>>1)]=(temp1-w*temp2%P+P)%P; } if(type!=1) { long long inv=Quick_Power(n,P-2,P); for(i=0;i<n;i++) a[i]=inv*a[i]%P; }}void Polynomial_Multiplication(int a[],int b[],int c[],int n){ static int A[3][M],B[3][M]; static const long long Inv[3]={644348675,675933219,647895261}; int i,j; for(j=0;j<3;j++) { for(i=0;i<n;i++) { A[j][i]=a[i]%P[j]; B[j][i]=b[i]%P[j]; } FFT(A[j],n,1,P[j],G[j]); FFT(B[j],n,1,P[j],G[j]); for(i=0;i<n;i++) A[j][i]=(long long)A[j][i]*B[j][i]%P[j]; FFT(A[j],n,P[j]-2,P[j],G[j]); } Int_128 _MOD=Int_128((long long)P[0]*P[1])*P[2]; for(i=0;i<n;i++) { Int_128 temp= Int_128((long long)P[1]*P[2])*Int_128(Inv[0]*A[0][i])+ Int_128((long long)P[0]*P[2])*Int_128(Inv[1]*A[1][i])+ Int_128((long long)P[0]*P[1])*Int_128(Inv[2]*A[2][i]); c[i]=(temp%_MOD%MOD).b; }}void Get_Inv(int a[],int b[],int n){ static int temp[M]; int i; if(n==1) { b[0]=Quick_Power(a[0],MOD-2,MOD); return ; } Get_Inv(a,b,n>>1); memcpy(temp,a,sizeof(a[0])*n); memset(temp+n,0,sizeof(a[0])*n); Polynomial_Multiplication(temp,b,temp,n<<1); memset(temp+n,0,sizeof(a[0])*n); for(i=0;i<n;i++) temp[i]=(MOD-temp[i])%MOD; (temp[0]+=2)%=MOD; Polynomial_Multiplication(temp,b,b,n<<1); memset(b+n,0,sizeof(a[0])*n);}void Get_Ln(int a[],int b[],int n){ static int a_[M],a_inv[M]; int i; Get_Inv(a,a_inv,n); for(i=0;i<n-1;i++) a_[i]=(long long)a[i+1]*(i+1)%MOD; Polynomial_Multiplication(a_,a_inv,b,n<<1); for(i=n-1;i;i--) b[i]=b[i-1]*inv[i]%MOD; b[0]=0; memset(b+n,0,sizeof(b[0])*n); memset(a_,0,sizeof(a_[0])*n<<1); memset(a_inv,0,sizeof(a_inv[0])*n<<1);}void Get_Exp(int a[],int b[],int n){ static int temp[M]; int i; if(n==1) { b[0]=1; return ; } Get_Exp(a,b,n>>1); memset(temp,0,sizeof(temp[0])*n<<1); Get_Ln(b,temp,n); for(i=0;i<n;i++) temp[i]=((i==0)+MOD-temp[i]+a[i])%MOD; Polynomial_Multiplication(b,temp,b,n<<1); memset(b+n,0,sizeof(b[0])*n);}int main(){ static int A[M],B[M],C[M]; int i; cin>>n; Pretreatment(); for(m=1;m<=n;m<<=1); for(A[1]=1,i=2;i<m;i++) A[i]=(long long)A[i-1]*inv[i]%MOD; Get_Exp(A,B,m); Polynomial_Multiplication(A,B,C,m<<1); long long ans=C[n]; for(i=1;i<=n;i++) (ans*=i)%=MOD; cout<<ans<<endl; return 0;}
0 0
- codeforces #568B Symmetric and Transitive 快速傅里叶变换
- CodeForces #315 (div1) B.Symmetric and Transitive
- codeforces #315B. Symmetric and Transitive dp
- codeforces 568B B. Symmetric and Transitive(贝尔数+组合数学)
- Codeforces Round #315 (Div. 1) B. Symmetric and Transitive 斯特林数 贝尔数
- CF 568B Symmetric and Transitive 贝尔数和stirlinig数
- Codeforces Round #315 (Div. 2) D. Symmetric and Transitive
- codeforces 569 D. Symmetric and Transitive (bell数)
- [组合数+bell数] codeforces 569D. Symmetric and Transitive
- Codeforces Round #315 (Div. 1) B. Symmetric and Transitive(Bell数的应用)(好题)
- Codeforces Round #315 (Div. 2)569D Symmetric and Transitive(dp)
- codeforces #250E The Child and Binary Tree 快速傅里叶变换
- Codeforces 450B Jzzhu and Sequences(矩阵快速幂)
- Codeforces #257B Jzzhu and Sequences(矩阵快速幂)
- Codeforces 450B Jzzhu and Sequences(矩阵快速幂)
- Codeforces 450B-Jzzhu and Sequences (矩阵快速幂)
- codeforces 450-B Jzzhu and Sequences 矩阵快速幂
- Codeforces 450B Jzzhu and Sequences(矩阵快速幂)
- 事物不回滚
- qualcomm platform camera
- 第七周项目一~~顺序环形队列算法库
- Xcode 6 正式版如何创建一个Empty Application
- Android与JavaScrpit相互调用
- codeforces #568B Symmetric and Transitive 快速傅里叶变换
- 面向对象程序设计的思想
- Hibernate List 转 Json 报错
- android中URLConnection和HttpURLConnection
- 解读ASP.NET 5 & MVC6系列(14):View Component
- 第四周项目2—建设“单链表”算法库
- ObjectC----NSDate和Extension以及代理协议的用法
- android---动态管理控件
- 【codevs2800】送外卖 floyd+状压DP