zoukankan      html  css  js  c++  java
  • Solution -「洛谷 P4451」「国家集训队」整数的 lqp 拆分

    Description

    Link.

    [sumprod_{i=1}^{m}F_{a_{i}},(m>0,a_{1},cdots a_{m}>0,sum a_{i}=n) ]

    Solution

    这是一篇不用 (mathbf{OGF}) 的题解。

    (f_{i})(i)(operatorname{lqp}) 拆分值。

    然后有显然的过不了递推式:

    [f_{n}=egin{cases} 1,n=0 \ displaystyle sum_{i=0}^{n-1}F_{n-i} imes f_{i},n eq0 end{cases} ]

    然后传统艺能错位相减操作一下:

    [egin{aligned} f_{n}&=sum_{i=0}^{n-1}F_{n-i} imes f_{i} \ f_{n-1}&=sum_{i=0}^{n-2}F_{n-i-1} imes f_{i} \ f_{n-2}&=sum_{i=0}^{n-3}F_{n-i-2} imes f_{i} end{aligned} Longrightarrow egin{aligned} f_{n}-f_{n-1}-f_{n-2}&=sum_{i=0}^{n-1}F_{n-i} imes f_{i}-sum_{i=0}^{n-2}F_{n-i-1} imes f_{i}-sum_{i=0}^{n-3}F_{n-i-2} imes f_{i} \ f_{n}-f_{n-1}-f_{n-2}&=(F_{2}-F_{1}) imes f_{n-2}+F_{1} imes f_{n-1} end{aligned} \ downarrow \ f_{n}=2f_{n-1}+f_{n-2} ]

    递推公式有了,然后矩阵快速幂:

    [egin{bmatrix} f_{n} \ f_{n-1} end{bmatrix} =egin{bmatrix} 2f_{n-1}+f_{n-2} \ f_{n-1} end{bmatrix} =egin{bmatrix} f_{n-1} \ f_{n-2} end{bmatrix} imesegin{bmatrix} 2 & 1 \ 1 & 0 end{bmatrix} ]

    这样就可以做了(吗?):

    (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] << '
    ';
    	return 0;
    }
    

    不,凉心出题人友好地卡了高精的常数,于是你打开题解,发现 (f_{n}=f_{nmod (10^{9}+6)}),于是你又行了。

    (mathcal{Code})

    #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( '
    ' );
    	return 0;
    }
    
  • 相关阅读:
    Spoj-DWARFLOG Manipulate Dwarfs
    Spoj-DRUIDEOI Fata7y Ya Warda!
    LightOJ1106 Gone Fishing
    LightOJ1125 Divisible Group Sums
    hdu5396 Expression
    cf715B Complete The Graph
    cf601A The Two Routes
    cf602B Approximating a Constant Range
    cf602A Two Bases
    认证方式
  • 原文地址:https://www.cnblogs.com/orchid-any/p/13884346.html
Copyright © 2011-2022 走看看