zoukankan      html  css  js  c++  java
  • AGC005D ~K Perm Counting

    Link
    考虑建立一个左右侧均有(n)个点的完全二分图,设左右侧点分别为(L_1,cdots,L_n,R_1,cdots R_n)
    显然这个二分图的完美匹配与(n)个元素的排列一一对应,具体而言设(L_ileftrightarrow R_{p_i}),那么这个完美匹配就与排列({p})对应。
    而题目给定的限制要求就相当于去掉((L_i,R_{ipm k}))这些边。
    (f_i)表示该二分图中大小为(i)的匹配个数,那么答案就是(sumlimits_{i=0}^n(-1)^i(n-i)!f_i)
    利用dp可以轻松地在(O(n^2))的时间复杂度下求出(f),不难发现可以利用多项式优化至(O(nlog n))

    #include<cstdio>
    const int N=4007,P=924844033;
    int f[N][N][2],vis[N];
    void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
    void dec(int&a,int b){a-=b,a+=a>>31&P;}
    int mul(int a,int b){return 1ll*a*b%P;}
    int main()
    {
        int n,k,x,y=0,ans=0;
        scanf("%d%d",&n,&k),x=(n-1)/k+1,f[0][0][1]=1;
        for(int i=((n-1)%k+1)*2;i;--i) vis[y+=x]=1;
        for(;y<2*n;) vis[y+=x-1]=1;
        for(int i=1;i<=2*n;++i)
    	for(int j=0;j<=n;++j)
    	{
    	    f[i][j][0]=f[i][j][1]=f[i-1][j][1];
    	    if(!vis[i-1]&&j) inc(f[i][j][1],f[i-1][j-1][0]);
    	}
        for(int i=0,k=1;i<=n;k=mul(k,++i)) ((n-i)&1? dec:inc)(ans,mul(f[2*n][n-i][1],k));
        printf("%d",ans);
    }
    
  • 相关阅读:
    Kotlin 基础
    ViewPager2
    8086-debug指令
    (四)主控板改IP,升级app,boot,mac
    (三)主控板生级uboot与内核
    (四)linux网络编程
    (七)嵌入式系统异常程序远程定位
    (六)ARM状态寄存器-PSR
    (五)stm32工程代码HardFault异常查错调试方法
    (十)makefile
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12694768.html
Copyright © 2011-2022 走看看