ACM题集:https://blog.csdn.net/weixin_39778570/article/details/83187443
题目链接:https://code.mi.com/problem/list/view?id=137&cid=7
小爱同学有一个智能密码锁。锁上有九位数字,小爱同学每次会给A,B,C,D,mod,n六个正整数。
题目是这样的:
F(1) = A, F(2) = BF(1)=A,F(2)=B
F(n) = F(n-1) * F(n-2) * C^D (n >= 2)
F(n)=F(n−1)⋅F(n−2)⋅C^D (n>2)
现在小爱同学想计算出 G(n) 的值(G(n)为F(n)的前n项积),并用该值作为密码锁的密码。
由于结果过大,所以答案 G(n)%mod
多组数据。每组包含 6 个整数,分别代表 A, B, C, D, mod, n. (1<=A,B,C,D,mod,n<=1000000000);
数据组数不超过2000.
------------------------------------------------------------------------------------------
斐波那契前缀和
因为乘积满足幂加的关系
容易知道要求幂的斐波那契数列
然后要求前n项和可知是斐波那契前缀和
又斐波那契前缀和与与后面第二项的差-1相等
重点是C^D这一项的幂....
观察规律可知是 fa+fb-n
fa为a的幂
fb为b的幂
(f*A*n) = [fib(n), fib(n+1)]下标0开始
n: 1 2 3 4 5 6 7 (以下表示幂)
B 0 1 1 2 3 5 8 13....这行是 Fib...
前缀和 0 1 2 4 7 12 20 sumA(n-1) = f(n+1)-1 = (f*A*n)[1]-1 下标从0开始
A 1 0 1 1 2 3 5 8
前缀和 1 1 2 3 5 8 13 sumB(n-1) = f(n) = (f*A*n)[0]
C^D 0 0 1 2 4 7 12
前缀和 0 0 1 3 7 14 26 sumC(n-1) = sumA(n-1) + sumB(n-1) - n
#include
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
ll a,b,c,d,mod,n,x,MOD;
int q_pow(ll a, ll n){
int ret = 1;
while(n){
if(n&1)ret = ret*a%mod;
a = a*a%mod;
n>>=1;
}
return ret%mod;
}
int phi(int n){
int ans = n;
for(int i=2; i<=sqrt(n); i++){
if(n%i==0){
ans = ans/i*(i-1);
while(n%i==0)n/=i;
}
}
if(n>1)ans = ans/n*(n-1);
return ans;
}
void mul(int f[2], int a[2][2]){
int c[2];
memset(c,0,sizeof c);
for(int j=0; j<2; j++){
for(int k=0; k<2; k++){
c[j] = (c[j] + (ll)f[k]*a[k][j])%MOD;
}
}
memcpy(f,c,sizeof(c));
}
void mulself(int a[2][2]){
int c[2][2];
memset(c,0,sizeof(c));
for(int i=0; i<2; i++){
for(int j=0;j<2; j++){
for(int k=0; k<2; k++){
c[i][j] = (c[i][j]+(ll)a[i][k]*a[k][j])%MOD;
}
}
}
memcpy(a,c,sizeof(c));
}
void solve(){
int f[2] = {0,1};
int A[2][2] = {{0,1},{1,1}};
int t = n;
for(;t;t>>=1){
if(t&1)mul(f, A);
mulself(A);
}
// cout<<"fib:"<
ll fa = f[0] + MOD; // f(n+1)
ll fb = f[1]-1 + MOD; // f(n+2)-1,斐波那契前缀和为后面第二项减1
ll fc = fa + fb - n % MOD + MOD; // 通过观察规律C^D 的幂 为 fa+fb-n
c = q_pow(c, d%MOD+MOD); // C^D
ll ans = q_pow(a,fa)%mod * q_pow(b,fb)%mod * q_pow(c,fc)%mod;
printf("%09d\n",ans);
}
int main(){
while(cin>>a>>b>>c>>d>>mod>>n){
MOD = phi(mod);
solve();
}
return 0;
}