赞
踩
解题思路:p/n在一些区间内是相同的,找出这些区间用矩阵快速幂即可,区间右端点可以二分找也可以
//int j=P/i==0?n:min(n,P/(P/i));这样找,目前还不知道为什么可以这样0(1)的找。
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- using namespace std;
- #define LL long long
- const LL mod =1e9+7;
- int A,B,C,D,P,n;
- struct node
- {
- LL a[4][4];
- node()
- {
- memset(a,0,sizeof(a));
- }
- };
-
- node operator *(node x,node y)
- {
- node tmp;
- for(int i=1;i<=3;i++)
- {
- for(int j=1;j<=3;j++)
- {
- for(int k=1;k<=3;k++)
- {
- tmp.a[i][j]=(tmp.a[i][j]+(x.a[i][k]*y.a[k][j])%mod)%mod;
- }
- }
- }
- return tmp;
- }
-
- void Print(node t)
- {
- for(int i=1;i<=3;i++)
- {
- for(int j=1;j<=3;j++)
- {
- cout<<t.a[i][j]<<" ";
- }
- cout<<endl;
- }
- }
-
- node qpow(node tmp,int k)
- {
- node t;
- t.a[1][1]=D,t.a[1][2]=1;
- t.a[2][1]=C,t.a[3][1]=1;
- t.a[3][3]=1,t.a[3][2]=0;
- while(k)
- {
- if(k&1)
- tmp=tmp*t;
- t=t*t;
- k>>=1;
- }
- return tmp;
- }
-
- int solve(int s)
- {
- int l=s;
- int r=n;
- int tmp=P/l;
- int cnt=33;
- while(cnt--)
- {
- //cout<<l<<" "<<r<<" "<<tmp<<endl;
- int m=(l+r)>>1;
- if((P/m)<tmp)
- {
- r=m-1;
- }
- else if((P/m)>tmp)l=m+1;
- else l=m;
- }
- return l;
- }
-
- int main()
- {
- int t;
- cin>>t;
- while(t--)
- {
- scanf("%d%d%d%d%d%d",&A,&B,&C,&D,&P,&n);
- LL f1=A;
- LL f2=B;
- if(n==1)
- {
- printf("%d\n",A);
- continue;
- }
- if(n==2)
- {
- printf("%d\n",B);
- continue;
- }
- for(int i=3;i<=n;)
- {
- //int j=P/i==0?n:min(n,P/(P/i));
- int j=solve(i);
- node tmp;
- tmp.a[1][1]=f2,tmp.a[1][2]=f1;
- tmp.a[1][3]=(P/i)*1LL;
- node kuai=qpow(tmp,j-i+1);
- f2=kuai.a[1][1],f1=kuai.a[1][2];
- i=j+1;
- }
- printf("%lld\n",f2);
- }
- }
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。