//zjx666的可回收垃圾
#include<iostream>
#include<map>
#include<cstring>
using namespace std;
long long t,n,q;
long long w=1000000007;
const int maxn=100010;
struct A{long long x,y;};//系数和常数项
long long k[maxn];
long long b[maxn];
long long d[maxn][35];//步数倍增 (大胆开不要怕炸,因为开小了会wa T-T)
A v[maxn][35];//函数倍增
long long s[maxn];
int main()
{
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
s[0]=1;
for(int i=1;i<=32;i++)
s[i]=s[i-1]*2;//预处理2^i步长
cin>>t;
while(t--)
{
cin>>n>>q;
for(int i=1;i<=n;i++)
cin>>k[i];
for(int i=1;i<=n;i++)
cin>>b[i];
for(int i=1;i<=n;i++)
{
cin>>d[i][0];
v[i][0].x=k[d[i][0]];//向前走一步,kx+b
v[i][0].y=b[d[i][0]];
}
for(int j=1;j<=32;j++)//倍增降低时间复杂度
{
for(int i=1;i<=n;i++)
{
d[i][j]=d[d[i][j-1]][j-1];
v[i][j].x=v[i][j-1].x*v[d[i][j-1]][j-1].x%w;//k2(k1x+b1)+b2
v[i][j].y=(v[d[i][j-1]][j-1].x*v[i][j-1].y+v[d[i][j-1]][j-1].y)%w;
}
}
while(q--)
{
int xi,di,yi;//10^9步长所以要预处理
A ans;
ans.x=1;
ans.y=0;
cin>>xi>>di>>yi;
for(int i=32;i>=0&&di>0;i--)//大到小减一定可以减完
{
if(di>=s[i])
{
ans.x=ans.x*v[xi][i].x%w;//同样维护复合函数系数
ans.y=(v[xi][i].x*ans.y+v[xi][i].y)%w;
di=di-s[i];//向前跳s[i]步
xi=d[xi][i];
}
}
cout<<(ans.x*yi%w+ans.y%w)%w<<"\n";//新的kx+b
}
}
return 0;
}
2023杭电多校(6)1010补题
于 2023-08-05 00:06:27 首次发布