前置知识:矩阵快速幂(自行优快云)
tag:图论+DP+矩阵快速幂优化
关键点1:v[i] >= u[i]+1 则说明一定为拓扑图
关键点2:又考虑到每层的DP转移只与上一层节点有关,且转移是线性的,考虑矩阵快速幂优化
实现:乘法原理求方案数,若没有边权才可用加法(相当于乘1)
到达i号节点的方案数 = 到达v的方案数(v能到i) * v->i的边权
dp[i]表示到点i的方案数,A[i]表示到第i层的点A的方案数,A[i]=层间转移数*层内转移数
层间转移
A[2]+=dp[5] =0*A[1]+0*B[1]+1*C[1]+0*D[1] 0 0 1 0
B[2]+=dp[6]=dp[1]+dp[3] =1*A[1]+0*B[1]+1*C[1]+0*D[1] 1 0 1 0
C[2]+=dp[7]=dp[2] =0*A[1]+1*B[1]+0*C[1]+0*D[1] 0 1 0 0
D[2]+=dp[8]=dp[4] =0*A[1]+0*B[1]+0*C[1]+1*D[1] 0 0 0 1
层内转移
A[2]+=dp[5]= 0 0 0 0 0
B[2]+=dp[6]=dp[5]=A[2] 1 0 0 0
C[2]+=dp[7]=dp[6]=B[2] 0 1 0 0
D[2]+=dp[8]=dp[5]+dp[6]+dp[7]=A[2]+B[2]+C[2] 1 1 1 0
最终转移式
A[2]=0*A[1]+0*B[1]+1*C[1]+0*D[1]
B[2]=1*A[1]+0*B[1]+2*C[1]+0*D[1]
C[2]=1*A[1]+1*B[1]+2*C[1]+0*D[1]
D[2]=2*A[1]+1*B[1]+5*C[1]+1*D[1]
时间复杂度O(n^3*log(1e18))
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=110;
const int mod=1e9+7;
const int INF=0x3f3f3f3f3f3f3f3f;
int n,m,L,R;
struct Matrix{
int a[N][N];
Matrix(int val){
for(int i=1;i<=n+1;++i){
for(int j=1;j<=n+1;++j){
a[i][j]=val;
}
}
}
Matrix operator*(Matrix b){
Matrix res(0);
for(int i=1;i<=n+1;++i){
for(int j=1;j<=n+1;++j){
for(int k=1;k<=n+1;++k){
res.a[i][j]=(res.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;
}
}
}
return res;
}
};
Matrix ksm(Matrix x,int k){
Matrix res(0);
for(int i=1;i<=n+1;++i)res.a[i][i]=1;
while(k){
if(k&1)res=res*x;
k>>=1;
x=x*x;
}
return res;
}
int ans[N];
int calc(Matrix a,int x){
int t1=x/n;
int t2=x%n;
Matrix t=ksm(a,t1);
int res=0;
for(int i=1;i<=n+1;i++){
res+=ans[i]*t.a[n+1][i]%mod;
res%=mod;
}
for(int i=1;i<=t2;i++){
int tt=0;
for(int j=1;j<=n+1;j++){
tt+=ans[j]*t.a[i][j]%mod;
tt%=mod;
}
res+=tt;
res%=mod;
}
return res;
}
void solve(){
cin>>n>>m>>L>>R;
for(int i=1;i<=n+1;i++)ans[i]=0;ans[1]=1;
Matrix base(0);
vector<vector<PII>> fa(n+1);
for(int i=0;i<m;i++){
int u,v,w;cin>>u>>v>>w;
if(v<=n)fa[v].push_back({u,w});
else base.a[v-n][u]+=w;
}
for(int i=1;i<=n;i++){
for(auto [v,w]:fa[i]){
ans[i]+=w*ans[v]%mod;
ans[i]%=mod;
}
}
for(int i=1;i<=n;i++){
for(auto [v,w]:fa[i]){
for(int j=1;j<=n;j++){
base.a[i][j]+=base.a[v][j]*w%mod;
base.a[i][j]%=mod;
}
}
}
for(int i=1;i<=n+1;i++)base.a[n+1][i]=1;
cout<<(calc(base,R)-calc(base,L-1)+mod)%mod<<endl;
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int _=1;
cin>>_;
while(_--)solve();
return 0;
}