zoukankan      html  css  js  c++  java
  • 【洛谷4463】[集训队互测2012] calc(动态规划+拉格朗日插值)

    点此看题面

    大致题意: 规定一个合法序列需要满足所有数都是([1,k])中互不相同的整数,且一个序列的值为该序列中所有数的乘积。求所有长度为(n)的合法序列值之和。

    动态规划

    首先由互不相同这个条件,不难想到强制序列有序,然后只要给最终答案乘上(n!)即可。

    于是就可以设(f_{i,j})表示对于前(i)个数,所取最大值小于等于(j)时的答案。(这样定义就能使得最终答案为(f_{n,k})

    转移只要判断当前位是否选择(j),即可得出方程:

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

    由于(k)的范围很大,这样肯定会(T)飞,因此就需要考虑一些玄学优化。

    拉格朗日插值

    这种优化(DP)的方式我真是死都想不到。。。

    考虑我们假设(f_{i,j})(j)(g(i))次函数,然后我们对原先的转移方程移项可以得到:

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

    一个众所周知的结论,对于一个(n)次函数(F(x))(F(x)-F(x-1))必然为(n-1)次函数。

    (F(x))恰好对应了此处的(f_{i,j})。也就是说,如果我们分别考虑等式两边(j)的次数,就可以列出一个有关次数的等式:

    [g(i)-1=g(i-1)+1Rightarrow g(i)=g(i-1)+2 ]

    又由于(g(0)=0),因此,最终我们发现(g(i)=2i),则(g(n)=2n)

    我们最后要求的只是(f_{n,k}),也就是一个(2n)次函数,那么我们只需要求出(2n+1)个点值,然后利用拉格朗日插值就可以求出(f_{n,k})了。

    (2n+1)个点值只需要(DP)(f_{n,1sim 2n+1}),那么每对((i,f_{n,i}))自然都是一个我们需要的点值。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 500
    using namespace std;
    int n,k,X,f[N+5][2*N+5],Fac[2*N+5];
    I int QI(RI x,RI y=X-2) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
    I int Lagrange(CI n,CI k,int *y)//拉格朗日插值(这里写的是x取值连续时的插值法,其实朴素的O(n^2)也可以)
    {
    	if(k<=n) return y[k];RI i,j,p=1,s=0;for(i=1;i<=n;++i) p=1LL*p*(k-i)%X;
    	for(i=1;i<=n;++i) s=(1LL*y[i]*QI(1LL*((n-i)&1?-1:1)*(k-i)%X*Fac[i-1]%X*Fac[n-i]%X)+s)%X;
    	return 1LL*p*s%X;
    }	
    int main()
    {
    	RI i,j;for(scanf("%d%d%d",&k,&n,&X),i=0;i<=2*n+1;++i) f[0][i]=1;//初始化
    	for(i=1;i<=n;++i) for(j=1;j<=2*n+1;++j) f[i][j]=(1LL*f[i-1][j-1]*j+f[i][j-1])%X;//DP
    	for(Fac[0]=i=1;i<=2*n+1;++i) Fac[i]=1LL*Fac[i-1]*i%X;//初始化阶乘
    	return printf("%d",1LL*Lagrange(2*n+1,k,f[n])*Fac[n]%X),0;//插值求出答案,记得乘上n的阶乘
    }
    
  • 相关阅读:
    Django中文无法转换成latin-1编码的解决方案
    JS-排序详解:冒泡排序、选择排序和快速排序
    javascript实例
    selenium webdriver 启动三大浏览器Firefox,Chrome,IE
    javascript教程5:--BOM操作
    python----图像简单处理(PIL or Pillow)
    Python模块学习之bs4
    采集淘宝美人库
    JavaScript 中的FileReader对象(实现上传图片预览)
    WPF
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu4463.html
Copyright © 2011-2022 走看看