zoukankan      html  css  js  c++  java
  • Luogu P4463 [国家集训队] calc

    WJMZBMR的题果然放在几年后看来仍然挺神,提出了一种独特的优化DP的方式

    首先我们想一个暴力DP,先定下所有数的顺序(比如强制它递增),然后最后乘上(n!)种排列方式就是答案了

    那么我们容易想出一个DP,令(f_{i,j})表示前(i)个数中,最大的数小于等于(j)的方案数是多少

    显然有转移:

    [f_{i,j}=f_{i-1,j-1} imes j+f_{i,j-1} ]

    但这样DP是(O(nA))的,需要用拉格朗日插值进行优化,不会拉格朗日插值的可以看一下浅谈拉格朗日插值

    在里面就提到了插值的一个关键点就是求出给定多项式的次数。因此我们观察(f_{n,i}),猜测它是关于(i)(t_n)次多项式

    那么我们把转移方程移项一下:

    [f_{i,j}-f_{i,j-1}=f_{i-1,j-1} imes j ]

    有差分和乘积的一些相关性质可以得出它们之间次数的关系:

    [t_n-1=t_{n-1}+1 ]

    而当(n=0)时,有(t_0=0),所以容易推出(t_n=2n)

    因此我们知道了(f_{n,i})是关于(i)(2n)次多项式,那么直接暴力DP求出(f_{n,1})(f_{n,2n+1}),然后插值出(f(n,A))的值即可

    CODE

    #include<cstdio>
    #define RI register int
    #define CI const int&
    using namespace std;
    const int N=505;
    int A,n,m,f[N][N<<1],g[N<<1],fact[N<<1],mod;
    inline int sum(CI a,CI b)
    {
        int t=a+b; return t>=mod?t-mod:t;
    }
    inline int sub(CI a,CI b)
    {
        int t=a-b; return t<0?t+mod:t;
    }
    inline int quick_pow(int x,int p=mod-2,int mul=1)
    {
        for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
    }
    inline void DP(CI n,CI m)
    {
        RI i,j; for (RI i=0;i<=m;++i) f[0][i]=1;
        for (i=1;i<=n;++i) for (j=1;j<=m;++j)
        f[i][j]=sum(1LL*f[i-1][j-1]*j%mod,f[i][j-1]);
    }
    inline int Lagerange(CI n,int *f,CI k)
    {
        if (k<=n) return f[k]; RI i; int ret=0,mt=1;
        for (i=1;i<=n;++i) mt=1LL*mt*(k-i)%mod; for (i=1;i<=n;++i)
        {
            int tp=1LL*mt*quick_pow(k-i)%mod*f[i]%mod;
            int dv=1LL*fact[i-1]*fact[n-i]%mod; tp=1LL*tp*quick_pow(dv)%mod;
            if ((n-i)&1) ret=sub(ret,tp); else ret=sum(ret,tp);
        }
        return ret;
    }
    int main()
    {
        scanf("%d%d%d",&A,&n,&mod); DP(n,m=n<<1|1);
        RI i; for (i=1;i<=m;++i) g[i]=f[n][i];
        for (fact[0]=i=1;i<=m;++i) fact[i]=1LL*fact[i-1]*i%mod;
        return printf("%d",1LL*Lagerange(m,g,A)*fact[n]%mod),0;
    }
    
  • 相关阅读:
    算法竞赛入门经典习题2-3 韩信点兵
    ios入门之c语言篇——基本函数——5——素数判断
    ios入门之c语言篇——基本函数——4——数值交换函数
    144. Binary Tree Preorder Traversal
    143. Reorder List
    142. Linked List Cycle II
    139. Word Break
    138. Copy List with Random Pointer
    137. Single Number II
    135. Candy
  • 原文地址:https://www.cnblogs.com/cjjsb/p/11055045.html
Copyright © 2011-2022 走看看