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;
    }
    
  • 相关阅读:
    赫尔维茨公式
    从解析几何的角度分析二次型
    Struts 1 Struts 2
    记一次服务器被入侵的调查取证
    契约式设计 契约式编程 Design by contract
    lsblk df
    Linux Find Out Last System Reboot Time and Date Command 登录安全 开关机 记录 帐号审计 历史记录命令条数
    Infrastructure for container projects.
    更新文档 版本控制 多版本并发控制
    Building Microservices: Using an API Gateway
  • 原文地址:https://www.cnblogs.com/orchid-any/p/13884346.html
Copyright © 2011-2022 走看看