zoukankan      html  css  js  c++  java
  • 数值微分(数学)(组合数)




    看到题目我们有一个直观的想法,就是它的递推式很像组合数学中的杨辉三角。。。。

    这样想的话很容易就能得出式子:

    [f[m](i)=sum_{j=0}^{i}f(i-j) imes C_{m}^{j} imes (-1)^j ]

    举个例子:
    (f[4](3))
    (=f[3](3)-f[3](2))
    (=f[2](3)-2 imes f[2](2)+f[2](1))
    (=f[1](3)-3 imes f[1](2)+3 imes f[1](1)-f[1](0))
    因为(f[1](0))是0,可以转换为(f[0](0))
    所以原式
    (=f[0](3)-4 imes f[0](2)+6 imes f[0](1)-4 imes f[0](0))

    那么接下来就是求组合数的问题了。

    求组合数的方法有很多种,这里借鉴maomao9173 dalao的总结:

    • 公式法 (这个复杂度很劣)
    • 阶乘逆元求法 适用于多次查询,复杂度预处理O( n+logn ),查询接近O( 1 ),但是模数必须是质数。(100007不是质数)
      (就是先O(n)预处理阶乘,然后算出来最大数的逆元,然后倒推回来。)
    • 杨辉三角递推求法 适用于多次密集小范围查询,复杂度预处理O( n^2 ),查询O( 1 )
      (比如说NOIP2016day2t1)
    • 费马小定理/exgcd求逆元 单次O( logn ),是最简单的方法,模数必须为质数
    • 阶乘分解 适用于模数不为质数的求法。复杂度预处理O( nlogn ),查询O( 1 )

    而这个题就是用阶乘分解的方法来做。

    [C_m^j=frac{m(m-1)...(m-j+1)}{j!} ]

    上下分别分解质因数,由于j!中的质因子都不超过n,所以只分解出2到n之间的质因子就可以了。

    分解之后分子分母先对分解的因子进行约分,组合数是整数所以约分之后分母必定全部消去,剩下的分子只需要乘法计算。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 1050;
    const int Mod = 100007;
    int n,m;
    int dr[N];
    int zuhe[N];
    int xu[N][N],cxu[N][N],vxu[N];
    int jia(int x,int y)
    {
    	x+=y;
    	if(x>=Mod)
    		x-=Mod;
    	return x;
    }
    int jian(int x,int y)
    {
    	x-=y;
    	if(x<0)
    		x+=Mod;
    	return x;
    }
    int cheng(int x,int y)
    {
    	long long z=x;
    	z*=y;
    	z%=Mod;
    	x=z;
    	return x;
    }
    //dalao说把取模题中的加减乘操作都写成函数
    //来替代常规的运算可以有效地避免取模出锅 
    int main()
    {
    	//freopen("difer.in","r",stdin);
    	//freopen("difer.out","w",stdout);
    	int i,j,k;
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++)
    		scanf("%d",&dr[i]);
    	for(i=1;i<=n && i<=m;i++)
    	{
    		xu[i][0]=m+1-i; 
    		for(j=2;j<=n;j++)
    		{
    			while(xu[i][0]%j==0)
    			{
    				xu[i][0]/=j;
    				xu[i][j]++;
    			}
    		}
    		//二维上面存储的是质因子为k,数组表示的是其对应的个数 
    		xu[i][0]%=Mod;
    	}
    	//预先处理出[m,m-i+1]其中每个数的质因子(这些在分子上面) 
    	for(i=1;i<=n && i<=m;i++)
    	{
    		cxu[i][0]=i;
    		for(j=2;j<=n;j++)
    		{
    			while(cxu[i][0]%j==0)
    			{
    				cxu[i][0]/=j;
    				cxu[i][j]++;
    			}
    		}
    	}
    	//预先处理出[1,i]其中每个数的质因子(这些在分母上) 
    	//操作同上 
    	zuhe[0]=1;
    	for(i=1;i<=n && i<=m;i++)
    	{
    		zuhe[i]=1;
    		for(j=1;j<=i;j++)
    			zuhe[i]=cheng(zuhe[i],xu[j][0]);
    		for(j=2;j<=n;j++)
    			vxu[j]+=xu[i][j]-cxu[i][j];
    		//分母分子相消 
    		for(j=2;j<=n;j++)
    		{
    			for(k=1;k<=vxu[j];k++)
    				zuhe[i]=cheng(zuhe[i],j);
    		}
    		if(i&1)
    			zuhe[i]=jian(0,zuhe[i]);
    	}
    	for(i=1;i<=n;i++)
    	{
    		int res=0;
    		for(j=0;j<i && j<=m;j++)
    			res=jia(res,cheng(dr[i-j],zuhe[j]));
    		//最后把答案累计出来qwq 
    		printf("%d
    ",res);
    	}
    	return 0;
    }
    
  • 相关阅读:
    141. Linked List Cycle【easy】
    237. Delete Node in a Linked List【easy】
    234. Palindrome Linked List【easy】
    排序_归并排序
    排序_选择排序
    排序_快速排序
    排序_冒泡排序
    排序_希尔排序
    排序_插入排序
    121. Best Time to Buy and Sell Stock【easy】
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9781572.html
Copyright © 2011-2022 走看看