Comet OJ Contest #13 D

Comet OJ Contest #13 D

\(\displaystyle \sum_{i=0}^{\left\lfloor\frac{n}{2}\right\rfloor} a^{i} b^{n-2 i}\left(\begin{array}{c}{n} \\ {2 i}\end{array}\right)\)

$ T \leq 10^4 , n , m , p \leq 10^{18} $

Note that since the $ p $ is not necessarily a prime number, and the data looks very fast power range all seemingly only fast power.

This formula can be turned into:

\(\displaystyle \sum_{i=0}^{\left\lfloor\frac{n}{2}\right\rfloor} {\sqrt a}^{2i} b^{n-2 i}\left(\begin{array}{c}{n} \\ {2 i}\end{array}\right)\)

Then in fact $ (\ sqrt a + b) ^ n $ and the even-order items.

Even number item can actually into $ \ frac {1} {2} ((\ sqrt a + b) ^ n - (\ sqrt a - b) ^ n) $ course, this is when $ n-$ is an even number, if to an odd turn.

This formula can be directly similar rapid power complex, because we will not know the last remaining root.

Of course, can be seen as the root of a characteristic equation, is a $ f (1) = 1, f (2) = b, f (n) = 2bf (n - 1) + (-b ^ 2 + a) f (n - 2) $.

/*Heroes Never Die!*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define int __int128_t
#define ll __int128_t
#define N 2
struct mtrx{
    ll a[3][3];
} tmp , cur , ans ;
ll a , b , P;
void mul( mtrx& a , mtrx& b ) {
    memset(tmp.a,0,sizeof tmp.a);
    for( ll i = 0 ; i < N ; ++ i )
        for( ll p = 0 ; p < N ; ++ p )
            if(a.a[i][p])
            for( ll j = 0 ; j < N ; ++ j )
                tmp.a[i][j] += a.a[i][p] * b.a[p][j] , tmp.a[i][j] %= P;
        
}

void power( ll n ) {
    memset(cur.a , 0 , sizeof cur.a) , memset(ans.a,0,sizeof ans.a);
    cur.a[0][0] = 2 * b % P , cur.a[0][1] = ( - b * b % P + a + P ) % P;
    cur.a[1][0] = 1;
    ans.a[0][0] = 1, ans.a[1][1] = 1;
    while( n ) {
        if( n & 1 ) mul( ans , cur ) , ans = tmp;
        mul( cur , cur ) , cur = tmp , n >>= 1 ;
    }
}
ll n;
inline __int128_t read()
{
   int X=0,w=0; char ch=0;
   while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
   while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
   return w?-X:X;
}
inline void print(__int128_t x)
{    
   if(x<0){putchar('-');x=-x;}
   if(x>9) print(x/10);
   putchar(x%10+'0');
}
signed main() {
    //freopen("input","r",stdin);
    signed T; cin >> T;
    while( T-- ){
        n = read() , a = read() , b = read( ) , P = read();
        power(n - 1);
        print((ans.a[0][0] * b % P + ans.a[0][1]) % P); puts("");
    }
}
//qwq

Guess you like

Origin www.cnblogs.com/yijan/p/cometoj13d.html