§ Description
Link.
求
§ Solution
这是一篇不用 的题解。
设 为 的 拆分值。
然后有显然的过不了递推式:
然后传统艺能错位相减操作一下:
递推公式有了,然后矩阵快速幂:
这样就可以做了(吗?):
(code?)
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#define mod ( 1000000007 )
using namespace std;
typedef long long LL;
template<typename _T, typename _P>
_T qkpow( _T bas, _T one, _P fur ){
_T res = one;
while( fur != 0 ){
if( fur % 2 == ( _P )1 ) res = bas * res;
bas = bas * bas;
fur /= 2;
}
return res;
}
template<typename _T>
_T add( _T x, _T y ){ if( y >= mod ) y %= mod; x += y; if( x >= mod ) x -= mod; return x; }
struct bigInt : vector<int>{
bigInt &check( ){
while( ! empty( ) && ! back( ) ) pop_back( );
if( empty( ) ) return *this;
for( unsigned i = 1; i < size( ); ++ i ){ ( *this )[i] += ( *this )[i - 1] / 10; ( *this )[i - 1] %= 10; }
while( back( ) >= 10 ){ push_back( back( ) / 10 ); ( *this )[size( ) - 2] %= 10; }
return *this;
}
bigInt( int tpN = 0 ){ push_back( tpN ); check( ); }
};
istream &operator >> ( istream &is, bigInt &tpN ){
string s;
is >> s; tpN.clear( );
for( int i = s.size( ) - 1; i >= 0; --i ) tpN.push_back( s[i] - '0' );
return is;
}
ostream &operator << ( ostream &os, const bigInt &tpN ){
if( tpN.empty( ) ) os << 0;
for( int i = tpN.size( ) - 1; i >= 0; --i ) os << tpN[i];
return os;
}
bool operator != ( const bigInt &one, const bigInt &another ){
if( one.size( ) != another.size( ) ) return 1;
for( int i = one.size( ) - 1; i >= 0; --i ){
if( one[i] != another[i] ) return 1;
}
return 0;
}
bool operator == ( const bigInt &one, const bigInt &another ){
return ! ( one != another );
}
bool operator < ( const bigInt &one, const bigInt &another ){
if( one.size( ) != another.size( ) ) return one.size( ) < another.size( );
for( int i = one.size( ) - 1; i >= 0; --i ){
if( one[i] != another[i] ) return one[i] < another[i];
}
return 0;
}
bool operator > ( const bigInt &one, const bigInt &another ){ return another < one; }
bool operator <= ( const bigInt &one, const bigInt &another ){ return ! (one > another ); }
bool operator >= ( const bigInt &one, const bigInt &another ){ return ! (one < another ); }
bigInt &operator += ( bigInt &one, const bigInt &another ){
if( one.size( ) < another.size( ) ) one.resize(another.size( ) );
for( unsigned i = 0; i != another.size( ); ++ i ) one[i] += another[i];
return one.check( );
}
bigInt operator + ( bigInt one, const bigInt &another ){ return one += another; }
bigInt &operator -= ( bigInt &one, bigInt another ){
if( one < another ) swap( one, another );
for( unsigned i = 0; i != another.size( ); one[i] -= another[i], ++ i ){
if( one[i] < another[i] ){
unsigned j = i + 1;
while( ! one[j] ) ++ j;
while( j > i ){ -- one[j]; one[--j] += 10; }
}
}
return one.check( );
}
bigInt operator - ( bigInt one, const bigInt &another ){ return one -= another; }
bigInt operator * ( const bigInt &one, const bigInt &another ){
bigInt tpN;
tpN.assign( one.size( ) + another.size( ) - 1, 0 );
for( unsigned i = 0; i != one.size( ); ++ i ){
for( unsigned j = 0; j != another.size( ); ++ j ) tpN[i + j] += one[i] * another[j];
}
return tpN.check( );
}
bigInt &operator *= ( bigInt &one, const bigInt &another ){ return one = one * another; }
bigInt divMod( bigInt &one, const bigInt &another ){
bigInt ans;
for( int t = one.size( ) - another.size( ); one >= another; -- t ){
bigInt tpS;
tpS.assign( t + 1, 0 );
tpS.back( ) = 1;
bigInt tpM = another * tpS;
while( one >= tpM ){ one -= tpM; ans += tpS; }
}
return ans;
}
bigInt operator / ( bigInt one, const bigInt &another ){ return divMod(one, another ); }
bigInt &operator /= ( bigInt &one, const bigInt &another ){ return one = one / another; }
bigInt &operator %= ( bigInt &one, const bigInt &another ){ divMod( one, another ); return one; }
bigInt operator % ( bigInt one, const bigInt &another ){ return one %= another; }
struct matrixS{
int mat[2][2];
matrixS( int x = 0 ){ memset( mat, x, sizeof( mat ) ); }
matrixS operator * ( const matrixS &another ) const{
matrixS res;
for( int i = 0; i < 2; ++ i ){
for( int j = 0; j < 2; ++ j ){
for( int k = 0; k < 2; ++ k ) res.mat[i][j] = add( ( LL )res.mat[i][j], ( LL )mat[i][k] * another.mat[k][j] );
}
}
return res;
}
} unit, erng;
bigInt N;
void progressBaseInformation( ){
int unitS[2][2] = { { 1, 0 }, { 0, 1 } };
memcpy( unit.mat, unitS, sizeof( unitS ) );
int erngS[2][2] = { { 2, 1 }, { 1, 0 } };
memcpy( erng.mat, erngS, sizeof( erngS ) );
}
signed main( ){
ios::sync_with_stdio( 0 ); cin.tie( 0 ); cout.tie( 0 );
progressBaseInformation( );
cin >> N; cout << qkpow( erng, unit, N ).mat[1][0] << '\n';
return 0;
}
不,凉心出题人友好地卡了高精的常数,于是你打开题解,发现 ,于是你又行了。
#include <cstdio>
#include <cstring>
#include <queue>
#define mod ( 1000000007 )
using namespace std;
typedef long long LL;
template<typename _T>
void read( _T &x ){
x = 0; char c = getchar( ); _T f = 1;
while( c < '0' || c > '9' ){ if( c == '-' ) f = -1; c = getchar( ); }
while( c >= '0' && c <= '9' ){ x = ( ( x << 3 ) + ( x << 1 ) + ( c & 15 ) ) % ( mod - 1 ); c = getchar( ); }
x *= f;
}
template<typename _T>
void write( _T x ){
if( x < 0 ){ putchar( '-' ); x = -x; }
if( x > 9 ) write( x / 10 );
putchar( x % 10 + '0' );
}
template<typename _T, typename _P>
_T qkpow( _T bas, _T one, _P fur ){
_T res = one;
while( fur != 0 ){
if( fur % 2 == ( _P )1 ) res = bas * res;
bas = bas * bas;
fur /= 2;
}
return res;
}
template<typename _T>
_T add( _T x, _T y ){ if( y >= mod ) y %= mod; x += y; if( x >= mod ) x -= mod; return x; }
struct matrixS{
int mat[2][2];
matrixS( int x = 0 ){ memset( mat, x, sizeof( mat ) ); }
matrixS operator * ( const matrixS &another ) const{
matrixS res;
for( int i = 0; i < 2; ++ i ){
for( int j = 0; j < 2; ++ j ){
for( int k = 0; k < 2; ++ k ) res.mat[i][j] = add( ( LL )res.mat[i][j], ( LL )mat[i][k] * another.mat[k][j] );
}
}
return res;
}
} unit, erng;
LL N;
void progressBaseInformation( ){
int unitS[2][2] = { { 1, 0 }, { 0, 1 } };
memcpy( unit.mat, unitS, sizeof( unitS ) );
int erngS[2][2] = { { 2, 1 }, { 1, 0 } };
memcpy( erng.mat, erngS, sizeof( erngS ) );
}
signed main( ){
progressBaseInformation( );
read( N ); write( qkpow( erng, unit, N ).mat[1][0] ), putchar( '\n' );
return 0;
}