在原始斐波那契数列上,第i项要加上 p/i
整除分块,复杂度根号nlogn(事实上不是,但是差不多这样)
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <cstring>
#define debug(x) //std::cerr << #x << " = " << (x) << std::endl
using namespace std;
typedef long long LL;
const int MAXN = 5e6 + 17;
const LL MOD = 1e9+7;
struct matrix{
static const int MATRIX_N = 5;
LL a[MATRIX_N][MATRIX_N];
int row, col;
matrix():row(MATRIX_N),col(MATRIX_N){memset(a,0,sizeof(a));}
matrix(int x, int y):row(x),col(y){memset(a,0,sizeof(a));}
LL* operator [] (int x){return a[x];}
matrix operator * (matrix x){
matrix tmp(row, x.col);
for(int i = 0; i < row; i++)
for(int j = 0; j < col; j++) if(a[i][j])
for(int k = 0; k < x.col; k++) if (x[j][k]){
tmp[i][k] = (tmp[i][k]+(a[i][j] * x[j][k])%MOD)%MOD;
tmp[i][k] %= MOD;
}
return tmp;
}
void operator *= (matrix x){*this = *this * x;}
matrix operator ^ (LL x){
matrix ret(row, col);
for (int i = 0; i < col; i++) ret[i][i] = 1;
matrix tmp = *this;
for (; x; x >>= 1, tmp *= tmp){if (x&1) ret *= tmp;}
return ret;
}
void print(){
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++) printf("%lld ",a[i][j]);
puts("");
}
puts("");
}
};
int dap[MAXN];
int main()
{
#ifdef noob
freopen("Input.txt", "r", stdin);
freopen("Output.txt", "w", stdout);
#endif
int t;
cin>>t;
while(t--)
{
LL a,b,c,d,p,n,q = 1;
scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&p,&n);
dap[0] = 2;
LL x = 0;
for(LL l=1,r;l<=n;l=r+1)
{
if(l>p)
{
dap[q++] = n;
break;
}
r=p/(p/l);
if(r>2)
dap[q++] = r;
}
LL fir = b,sec = a,zt,sz = q-1;
matrix ori(3,3);
ori[0][0] = d,ori[0][1] = c,ori[0][2] = 1;
ori[1][0] = 1,ori[1][1] = 0,ori[1][2] = 0;
ori[2][0] = 0,ori[2][1] = 0,ori[2][2] = 1;
matrix son(3,1);
for (LL r=0; r <= n;++x)
{
r = dap[x];
if(r>=n) break;
LL dis = n-r;
if(x<sz-1)
dis = min(dap[x+1]-r,dis);
if(dis<0) break;
zt = p/(r+dis);
son[0][0] = fir,son[1][0] = sec,son[2][0]=zt;
// son.print();
ori[0][0] = d,ori[0][1] = c,ori[0][2] = 1;
ori[1][0] = 1,ori[1][1] = 0,ori[1][2] = 0;
ori[2][0] = 0,ori[2][1] = 0,ori[2][2] = 1;
ori = ori^dis;
son = ori*son;
// ori.print();
// son.print();
fir = son[0][0];
sec = son[1][0];
}
printf("%lld\n",fir );
// cout<<fir<<endl;
}
return 0;
}
很不应该,整除分块几乎一瞬间就想到了,但是不知为何又否认了,应该是我对这个只有一个听过名字的印象,太糟糕了.