容易知道 p/i (i=3......n); 在某一区间内是相同的,记录前一个区间的fn-1,fn-2,对本区间进行矩阵快速幂,确定本区间的界限可以用一句话 即 j=(p/i)==0?n:min(n,p/(p/i)),并不需要二分;
AC 代码
#include <iostream>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=2e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
LL a[5][5],b[5][5],res[4][4];
void mul(LL t[5][5],LL t1[5][5])
{
memset(res,0,sizeof(res));
for (int i=0;i<3;i++)
for (int j=0;j<3;j++)
for (int k=0;k<3;k++)
res[i][j]=(res[i][j]+t[i][k]*t1[k][j]%mod)%mod;
for (int i=0;i<3;i++)
for (int j=0;j<3;j++)
t[i][j]=res[i][j];
}
void quc(LL a[5][5],LL pow)
{
memset(b,0,sizeof(b));
for (int i=0;i<3;i++)
b[i][i]=1;
LL temp[5][5];
for (int i=0;i<3;i++)
for (int j=0;j<3;j++)
temp[i][j]=a[i][j];
while (pow)
{
if (pow&1)
mul(b,temp);
mul(temp,temp);
pow>>=1;
}
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
cin>>t;
while (t--)
{
int A,B,C,D,p,n;
cin>>A>>B>>C>>D>>p>>n;
memset(a,0,sizeof(a));
a[0][0]=D;a[0][1]=C;a[0][2]=1;
a[1][0]=1;a[2][2]=1;
LL f_one,f_sec,fi=B%mod,fj=A%mod;
for (int i=3;i<=n;)
{
LL j=(p/i)==0?n:min(n,p/(p/i));
LL v=p/i;
quc(a,j-i+1);
f_one=((fi*b[0][0]%mod+fj*b[0][1]%mod)%mod+v*b[0][2]%mod)%mod;
f_sec=((fi*b[1][0]%mod+fj*b[1][1]%mod)%mod+v*b[1][2]%mod)%mod;
fi=f_one;
fj=f_sec;
i=j+1;
}
cout<<fi<<endl;
}
return 0;
}