Sequence
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1039 Accepted Submission(s): 388
Problem Description
Let us define a sequence as below
Your job is simple, for each task, you should output Fn module 109+7.
Input
The first line has only one integer T, indicates the number of tasks.
Then, for the next T lines, each line consists of 6 integers, A , B, C, D, P, n.
1≤T≤200≤A,B,C,D≤1091≤P,n≤109
Sample Input
2
3 3 2 1 3 5
3 2 2 2 1 4
Sample Output
36
24
Source
2018 Multi-University Training Contest 7
分段的矩阵快速幂要注意过程的转换,矩阵要回归最初的状态。
解析:向下取整的P/i在1~n中,会有重复的值,说明我们可以分段矩阵快速幂。二分查找相等的P/i的区间。(也可以O(1)目前不会,数论分块里应该有说明。)
构造的矩阵:
#include<bits/stdc++.h>
using namespace std;
#define e exp(1)
#define pi acos(-1)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define mem(a,b) memset(a,b,sizeof(a))
int gcd(int a,int b){return b?gcd(b,a%b):a;}
ll A,B,C,D,N,P;
struct mat
{
ll a[3][3];
}c;
mat mat_mul(mat x,mat y)
{
mat s;
mem(s.a,0);
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
s.a[i][j]=(s.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
return s;
}
mat mat_pow(ll n)
{
mat res;
mem(res.a,0);
res.a[0][0]=res.a[1][1]=res.a[2][2]=1;
while(n)
{
if(n&1) res=mat_mul(res,c);
c=mat_mul(c,c);
n>>=1;
}
return res;
}
ll solove(ll i)
{
ll l=i,r=N;
ll p=P/i;
while(l<r)
{
int mid=r-(r-l)/2;
if(p==P/mid)l=mid;
else if(p>P/mid)r=mid-1;
else l=mid+1;
}
return l;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%lld%lld%lld%lld%lld%lld",&A,&B,&C,&D,&P,&N);
if(N==1){printf("%lld\n",A);continue;}
if(N==2){printf("%lld\n",B);continue;}
ll f1=B;
ll f2=A;
mat ans;
for(ll i=3; i<=N;)
{
ll j=solove(i);
mem(c.a,0);
c.a[0][0]=D;c.a[0][1]=C;
c.a[2][2]=1;c.a[1][0]=1;
c.a[0][2]=P/i;
ans=mat_pow(j-i+1);
ll ff1=(ans.a[0][0]*f1%mod+ans.a[0][1]*f2%mod+ans.a[0][2])%mod;
ll ff2=(ans.a[1][0]*f1%mod+ans.a[1][1]*f2%mod+ans.a[1][2])%mod;
f1=ff1;
f2=ff2;
i=j+1;
}
printf("%lld\n",f1);
}
return 0;
}