zoukankan      html  css  js  c++  java
  • ZOJ 3874 Permutation Graph ——分治 NTT

    发现每一块一定是按照一定的顺序的。

    然后与标号无关,并且相同大小的对答案的影响相同。

    然后列出递推式,上NTT+分治就可以了。

    然后就可以与输入同阶处理答案了。

    #include <map>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define ll long long
    #define mp make_pair
    #define maxn (1<<18)
    #define md 786433
    #define g 10
    
    int dp[maxn],fac[maxn],A[maxn],B[maxn],t,n,m,rev[maxn],C[maxn];
    
    int ksm(int a,int b)
    {
    	int ret=1;
    	for(;b;b>>=1,a=(ll)a*a%md)if(b&1)ret=(ll)ret*a%md;
    	return ret;
    }
    
    void NTT(int * x,int n,int flag)
    {
    	F(i,0,n-1) if (rev[i]>i) swap(x[rev[i]],x[i]);
    	for (int m=2;m<=n;m<<=1)
    	{
    		int mid=m>>1,wn=ksm(10,((md-1)/m*flag+md-1)%(md-1));
    		for (int i=0;i<n;i+=m)
    		{
    			int w=1;
    			for (int j=0;j<mid;++j)
    			{
    				int u=x[i+j],v=(ll)x[i+j+mid]*w%md;
    				x[i+j]=(u+v)%md;x[i+j+mid]=((u-v)%md+md)%md;
    				w=(ll)w*wn%md;
    			}
    		}
    	}
    	if (flag==-1)
    	{
    		int inv=ksm(n,md-2);
    		F(i,0,n-1) x[i]=(ll)x[i]*inv%md;
    	}
    }
    
    void CDQ(int l,int r)
    {
    	if(l==r)return;int mid=l+r>>1;CDQ(l,mid);
    	int n=mid-l+r-l,m=1;while((1<<m)<n)++m;n=(1<<m);
    	F(i,0,n-1)A[i]=B[i]=0;
    	F(i,l,mid)A[i-l]=dp[i];F(i,1,r-l) B[i-1]=fac[i];
    	F(i,1,n-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(m-1));
    	NTT(A,n,1);NTT(B,n,1);
    	F(i,0,n-1)C[i]=(ll)A[i]*B[i]%md;NTT(C,n,-1);
    	F(i,mid+1,r)dp[i]=((dp[i]-C[i-l-1])%md+md)%md;
    	CDQ(mid+1,r);
    }
    
    int main()
    {
    	fac[0]=1; F(i,1,100000) fac[i]=(ll)fac[i-1]*i%md;
    	dp[0]=0; F(i,1,100000) dp[i]=fac[i];
    	CDQ(1,100000);
    	scanf("%d",&t);
    	while(t--)
    	{
    		int ans=1,k,x;
    		scanf("%d%d",&n,&m);
    		F(i,1,m)
    		{
    			int mn=n+1,mx=-1;
    			scanf("%d",&k); ans=(ll)ans*dp[k]%md;
    			F(j,1,k) scanf("%d",&x),mn=min(mn,x),mx=max(mx,x);
    			if (k!=mx-mn+1) ans=0;
    		}
    		printf("%d
    ",ans);
    	}
    }
    

      

  • 相关阅读:
    凌乱的DSP笔记(6)-直流电机&步进电机
    凌乱的DSP笔记(5)-按键
    凌乱的DSP笔记(4)-继电器
    凌乱的DSP笔记(3)-蜂鸣器播放音乐
    凌乱的DSP笔记(2)-LED流水灯
    凌乱的DSP笔记(1)-F28335基础知识
    Python GUI设计——tkinter菜鸟编程(上)
    Python基础知识
    R|Shiny练习
    R之ggvis学习笔记
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6776971.html
Copyright © 2011-2022 走看看