zoukankan      html  css  js  c++  java
  • 一种类似等比数列求和问题的解法

    有时,会遇到这样的问题:求 (sum_{i=1}^n i^kx^i)
    其中,k很小,n很大,x可以是数,矩阵,或多项式。
    通常,有两种做法:

    1. 将x放入矩阵中,并依次把((a+1)^i)拆开,把系数放入矩阵(其实就是杨辉三角)。
      这个方法比较容易,但时间复杂度为(O(k^3log n))

    2. 使用递归。从(frac n 2)的答案推到(n)的答案。
      根据n的奇偶性分类讨论。
      递归时维护0~k的所有答案。代码比较难写,注意细节。
      时间复杂度(O(k^2log n))

    例题:

    这道题比较卡常,需要使用方法二。
    代码:

    #include <stdio.h>
    #define md 1000000007
    void fuz(int a[102][102],int b[102][102],int n)
    {
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    			a[i][j]=b[i][j];
    	}
    }
    void chf(int a[102][102],int b[102][102],int n)
    {
    	int jg[102][102]={0};
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			if(a[i][j])
    			{
    				for(int k=1;k<=n;k++)
    					jg[i][k]=(jg[i][k]+1ll*a[i][j]*b[j][k])%md;
    			}
    		}
    	}
    	fuz(a,jg,n);
    }
    void chf(int a[102][102],int x,int n)
    {
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    			a[i][j]=1ll*a[i][j]*x%md;
    	}
    }
    void add(int a[102][102],int b[102][102],int n)
    {
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    			a[i][j]=(a[i][j]+b[i][j])%md;
    	}
    }
    int G[102][102],A[102][102],B[102][102],C[102][102],mi[102][102],ag[102][102],bg[102][102],cg[102][102],jh[102][102];
    void dfs(int m,int n)
    {
    	if(m==1)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			for(int j=1;j<=n;j++)
    				mi[i][j]=A[i][j]=B[i][j]=C[i][j]=G[i][j];
    		}
    		return;
    	}
    	if(m%2==0)
    	{
    		int z=m/2;dfs(z,n);
    		fuz(ag,A,n);
    		chf(ag,mi,n);
    		add(A,ag,n);
    		fuz(bg,B,n);
    		chf(bg,mi,n);
    		add(B,bg,n);
    		chf(ag,z,n);
    		add(B,ag,n);
    		fuz(cg,C,n);
    		chf(cg,mi,n);
    		add(C,cg,n);
    		chf(bg,z*2,n);
    		add(C,bg,n);
    		chf(ag,z,n);
    		add(C,ag,n);
    		chf(mi,mi,n);
    	}
    	else
    	{
    		int z=m/2;dfs(z,n);
    		fuz(jh,mi,n);z+=1;
    		chf(mi,G,n);
    		fuz(ag,A,n);
    		for(int i=1;i<=n;i++)
    			ag[i][i]=(ag[i][i]+1)%md;
    		chf(ag,mi,n);
    		add(A,ag,n);
    		fuz(bg,B,n);
    		chf(bg,mi,n);
    		add(B,bg,n);
    		chf(ag,z,n);
    		add(B,ag,n);
    		fuz(cg,C,n);
    		chf(cg,mi,n);
    		add(C,cg,n);
    		chf(bg,z*2,n);
    		add(C,bg,n);
    		chf(ag,z,n);
    		add(C,ag,n);
    		chf(mi,jh,n);
    	}
    }
    int main()
    {
    	int n,m,k,q;
    	scanf("%d%d%d%d",&n,&m,&k,&q);
    	for(int i=0;i<m;i++)
    	{
    		int a,b;
    		scanf("%d%d",&a,&b);
    		G[a][b]+=1;
    	}
    	dfs(k,n);
    	for(int i=0;i<q;i++)
    	{
    		int s,t;
    		scanf("%d%d",&s,&t);
    		printf("%d
    ",C[s][t]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Certificate、Provisioning Profile、App ID
    boundingRectWithSize
    IOS照片框架
    UIlabel 属性text
    UIMenuController的使用,对UILabel拷贝以及定制菜单
    iOS 自定义emoji表情键盘
    IOS第三方字体
    IOS 验证码
    网上收集的以及自己总结的iOS开发技巧
    给自己一个坚持下去的理由
  • 原文地址:https://www.cnblogs.com/lnzwz/p/13493304.html
Copyright © 2011-2022 走看看