Description

Link.

\[\sum\prod_{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}=\begin{cases}
1,n=0 \\
\displaystyle
\sum_{i=0}^{n-1}F_{n-i}\times f_{i},n\neq0
\end{cases}
\]

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

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

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

\[\begin{bmatrix}
f_{n} \\
f_{n-1}
\end{bmatrix}
=\begin{bmatrix}
2f_{n-1}+f_{n-2} \\
f_{n-1}
\end{bmatrix}
=\begin{bmatrix}
f_{n-1} \\
f_{n-2}
\end{bmatrix}
\times\begin{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] << '\n';
return 0;
}

不,凉心出题人友好地卡了高精的常数,于是你打开题解,发现 \(f_{n}=f_{n\bmod (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( '\n' );
return 0;
}

Solution -「洛谷 P4451」「国家集训队」整数的 lqp 拆分的更多相关文章

  1. 【洛谷】1852:[国家集训队]跳跳棋【LCA】【倍增?】

    P1852 [国家集训队]跳跳棋 题目背景 原<奇怪的字符串>请前往 P2543 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个 ...

  2. 【洛谷】1494:[国家集训队]小Z的袜子【莫队】

    P1494 [国家集训队]小Z的袜子 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… ...

  3. Solution -「国家集训队」「洛谷 P4451」整数的 lqp 拆分

    \(\mathcal{Description}\)   Link.   求 \[\sum_{m>0\\a_{1..m}>0\\a_1+\cdots+a_m=n}\prod_{i=1}^mf ...

  4. 洛谷P1903 数颜色 [国家集训队] 莫队

    正解:带修莫队 解题报告: 可以理解为引入时间参数,然后就是有了仨参数,关于这个修改同样的是,如果时间是相同的,不用搞,如果时间不相同做一下时光倒流/时光推移就成嘛 但是肯定既然这样的话,按照原来的s ...

  5. 题解 洛谷P1903/BZOJ2120【[国家集训队]数颜色 / 维护队列】

    对于不会树套树.主席树的本蒟蒻,还是老老实实的用莫队做吧.... 其实这题跟普通莫队差不了多远,无非就是有了一个时间,当我们按正常流程排完序后,按照基本的莫队来,做莫队时每次循环对于这一次操作,我们在 ...

  6. 题解 洛谷P1501/BZOJ2631【[国家集训队]Tree II】

    Link-Cut-Tree 的懒标记下传正确食用方法. 我们来逐步分析每一个操作. 1:+ u v c:将u到v的路径上的点的权值都加上自然数c; 解决方法: 很显然,我们可以 split(u,v) ...

  7. 洛谷 P1505 BZOJ 2157 [国家集训队]旅游

    bzoj题面 Time limit 10000 ms Memory limit 265216 kB OS Linux 吐槽 又浪费一个下午--区间乘-1之后,最大值和最小值更新有坑.新的最大值是原来最 ...

  8. 「区间DP」「洛谷P1043」数字游戏

    「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...

  9. 「 洛谷 」P2768 珍珠项链

    珍珠项链 题目限制 内存限制:125.00MB 时间限制:1.00s 标准输入输出 题目知识点 动态规划 \(dp\) 矩阵 矩阵乘法 矩阵加速 矩阵快速幂 题目来源 「 洛谷 」P2768 珍珠项链 ...

  10. 「 洛谷 」P4539 [SCOI2006]zh_tree

    小兔的话 推荐 小兔的CSDN [SCOI2006]zh_tree 题目限制 内存限制:250.00MB 时间限制:1.00s 标准输入输出 题目知识点 思维 动态规划 \(dp\) 区间\(dp\) ...

随机推荐

  1. Delegation Pattern 委托模式

    原文:https://zh.wikipedia.org/wiki/%E5%A7%94%E6%89%98%E6%A8%A1%E5%BC%8F 委托模式是软件设计模式中的一项基本技巧.在委托模式中,有两个 ...

  2. 【园子资深博主直播】 冰蓝老师《ChatGPT 初探》

    AI对经济增长.经济周期.经济形态.社会就业都有着非常巨大的影响,ChatGPT4.0发布后,燃起了我们每一个开发人的激情和恐惧,但各路自媒体信息杂乱无序,缺少非常系统性的ChatGPT原理解读. 此 ...

  3. @Deprecated注解的使用

    被注解@Deprecated标记的程序元素是不鼓励使用的程序元素,通常是因为它很危险,或者是因为存在更好的替代方案. 除了对象自身引用自己用@Deprecated标记的方法外,其他情况使用@Depre ...

  4. Spark SQL 及其DataFrame的基本操作

    1.Spark SQL出现的 原因是什么? Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个叫作Data Frame的编程抽象结构数据模型(即带有Schema信息的RDD),S ...

  5. 从隐私保护到AI隐私保护:隐私隐私保护的跨隐私保护治理框架实践案例

    目录 标题:<从隐私保护到AI隐私保护:跨隐私保护治理框架实践案例> 背景介绍 随着人工智能技术的广泛应用,隐私保护问题也日益突出.数据隐私泄露.算法歧视等问题引发了公众的担忧和不满.为了 ...

  6. 6大数据实战系列-sparkSql实战

    sparkSql两个最重要的类SqlContext.DataFrame,DataFrame功能强大,能够与rdd互转换.支持sql操作如sql().where.order.join.groupBy.l ...

  7. Python运维开发之路《数据类型》

    一. python数据类型 python的五大基本数据类型,数字.字符串.列表.元组.字典;其他数据类型,类型type.Null.文件.集合.函数/方法.类.模块. 1.数字 1 ①整型 2 十进制转 ...

  8. 一个跨平台的`ChatGPT`悬浮窗工具

    一个跨平台的ChatGPT悬浮窗工具 使用avalonia实现的ChatGPT的工具,设计成悬浮窗,并且支持插件. 如何实现悬浮窗? 在使用avalonia实现悬浮窗也是非常的简单的. 实现我们需要将 ...

  9. 基于词袋(Bag of Words)和SVM的图片分类

    目录 摘要 源码及完整报告: 词袋(Bag of Words, BoW) 基于词袋模型的图片分类基本流程 多尺度空间极值点检测 关键点精确定位 关键点主方向计算 生成描述子 特征词典的生成 SVM分类 ...

  10. GO网络编程(二)

    [[Go语言系列视频]老男孩带你21周搞定Go语言[全 242]] https://www.bilibili.com/video/BV1fD4y117Dg/?p=113&share_sourc ...