循环图

题目链接

  • 抽丝剥茧到最后一步,你离成功解出这道题只剩下“矩阵等比数列求和”这个问题了。把式子写出来:\(M+M^2+M^3+...+M^k\),虽然没办法套用求和公式,但一定有办法的,看着它,用心感受,或者不妨先转移注意力——
  • 分治!分解原问题为结构相同的子问题,再将子问题的解合并成原问题的解!
  • 分治的过程中,如果调用power函数,总的时间复杂度大概会多出一个log,这是不能接受的;不妨新开一个全局变量,在递归的过程中顺便计算快速幂的值
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int mod=1000000007;
long long L,R;
vector<long long>a[105],c[105];
long long f[105],ans;
long long n;
class matrix
{
    public:
        matrix()
        {
            memset(a,0,sizeof(a));
        }
        long long a[105][105];
        void clear()
        {
            memset(a,0,sizeof(a));
        }
};
matrix pr;
matrix danwei()
{
	matrix res;
	for(long long i=1;i<=n;i++)
	{
		res.a[i][i]=1;
	}
	return res;
}
matrix operator+(matrix a,matrix b)
{
    matrix c;
    for(long long i=1;i<=n;i++)
    {
        for(long long j=1;j<=n;j++)
        {
            c.a[i][j]+=(a.a[i][j]+b.a[i][j]);
            c.a[i][j]%=mod;
        }
    }
    return c;
}
matrix operator*(matrix a,matrix b)
{
    matrix c;
    for(long long i=1;i<=n;i++)
    {
        for(long long j=1;j<=n;j++)
        {
            for(long long k=1;k<=n;k++)
            {
                c.a[i][j]+=(a.a[i][k]*b.a[k][j]%mod);
            }
            c.a[i][j]%=mod;
        }
    }
    return c;
}
matrix power(matrix n1,long long p)
{
	matrix res=danwei();
	for(p;p;p>>=1)
	{
		if((p&1)==1)
		{
			res=res*n1;
		}
		n1=n1*n1;
	}
	return res;
}
matrix P;
matrix fenzhi(matrix n1,long long p)
{
	if(p==1)
	{
		P=n1;
		return n1;
	}
	matrix tmp=fenzhi(n1,p/2),q=P;
	if(p%2==0)
	{
		P=P*P;
		return tmp+tmp*q;
	}
	else
	{
		P=P*P*n1;
		return tmp+tmp*q+q*q*n1;
	}
}
void calc(long long l,long long r)
{
	if(l>r)
	{
		return;
	}
	else if(l==r)
	{
		matrix val=power(pr,l-1);
		for(long long i=1;i<=n;i++)
		{
			long long n1=(l-1)*n+i;
			if(n1>=L&&n1<=R)
			{
				for(long long j=1;j<=n;j++)
				{
					ans=ans+f[j]*val.a[i][j]%mod;
					ans%=mod;
				}
			}
		}
	}
	else
	{
		matrix val=power(pr,l-2)*fenzhi(pr,r-l+1);
		for(long long i=1;i<=n;i++)
		{
			for(long long j=1;j<=n;j++)
			{
				ans=ans+f[j]*val.a[i][j]%mod;
				ans%=mod;
			}
		}
	}
}
int main() 
{
	int size(512<<20);
	__asm__ ( "movq %0, %%rsp\n"::"r"((char*)malloc(size)+size));
	ios::sync_with_stdio(false);
	cin.tie(0);
    long long T;
    cin>>T;
    while(T--)
    {
        long long m;
        cin>>n>>m>>L>>R;
        pr.clear();
        for(long long i=1;i<=n;i++)
        {
        	f[i]=0;
            a[i].clear();
            c[i].clear();
        }
        for(long long i=1;i<=m;i++)
        {
            long long u,v,w;
            cin>>u>>v>>w;
            if(v<=n)
            {
                a[v].push_back(u);
                c[v].push_back(w);
            }
            else
            {
                pr.a[v-n][u]=w;
            }
        }
        f[1]=1;
        for(long long i=1;i<=n;i++)
        {
            for(long long j=0;j<a[i].size();j++)
            {
                (f[i]+=(c[i][j]*f[a[i][j]]%mod))%=mod;
                for(long long k=1;k<=n;k++)
                {
                    pr.a[i][k]+=(pr.a[a[i][j]][k]*c[i][j]%mod);
                    pr.a[i][k]%=mod;
                }
            }
        }
        long long l=(L-1)/n+1;
        long long r=(R-1)/n+1;
        ans=0;
        if(l==r)
        {
        	calc(l,l);
        }
        else
        {
        	calc(l,l);
        	calc(r,r);
        	calc(l+1,r-1);
        }
        cout<<ans<<endl;
    }    
    exit(0);
}
posted @ 2024-09-05 16:18  D06  阅读(7)  评论(0编辑  收藏  举报