• 一种类似等比数列求和问题的解法


    有时,会遇到这样的问题:求 (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;
    }
    
  • 相关阅读:
    win10 开机背景图
    关于在不知道具体实例化哪个窗体时调用该窗体公共变量的方法
    devexpress 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 “lc.exe”已退出,代码为 -1。
    获取打印机设置的纸张参数
    mysql 添加字段语句
    curl模拟post请求
    php CI框架log写入
    winform程序更新
    JSP的EL和JSTL解析
    报错:java.lang.IllegalArgumentException: object is not an instance of declaring class
  • 原文地址:https://www.cnblogs.com/lnzwz/p/13493304.html
Copyright © 2020-2023  润新知