2020/02/11 upd

更换markdown编辑器,修了一下写错了的式子


 

传送门

题目描述

热情好客的小猴子请森林中的朋友们吃饭,他的朋友被编号为 1?N,每个到来的朋友都会带给他一些礼物:大香蕉。其中,第一个朋友会带给他 1 个大香蕉,之后,每一个朋友到来以后,都会带给他之前所有人带来的礼物个数再加他的编号的K次方那么多个。所以,假设K=2,前几位朋友带来的礼物个数分别是:

1,5,15,37,83,…

假设K=3,前几位朋友带来的礼物个数分别是:

1,9,37,111,…

现在,小猴子好奇自己到底能收到第 N 个朋友多少礼物,因此拜托于你了。

已知 N,K,请输出第 N 个朋友送的礼物个数 mod 10^9+7。

输入格式

第一行,两个整数 N,K。

输出格式

一个整数,表示第 N 个朋友送的礼物个数 mod 10^9+7 。

输入输出样例

输入 #1

4 2

输出 #1

37

输入 #2

2333333 2

输出 #2

514898185

输入 #3

1234567890000 3

输出 #3

891659731

输入 #4

66666666 10

输出 #4

32306309

100% 的数据:\(N \le 10^{18}, K \le 10\)

暴搞通项公式

蒟蒻想了一上午弄出来个\(O(k^2)\)的算法

这道题比较裸,就是甩给你个递推式让你求第\(n\)项

\[A_1 = 1,A_n = \sum_{i=1}^{n-1} A_i + n^k
\]

那首先我们来手动打个表qwq

\(A_i\) \ \(i^k\) \(1^k\) \(2^k\) \(3^k\) \(4^k\) \(5^k\) \(6^k\)
\(A_1\) 1
\(A_2\) 1 1
\(A_3\) 2 1 1
\(A_4\) 4 2 1 1
\(A_5\) 8 4 2 1 1
\(A_6\) 16 8 4 2 1 1

表中第\(i\)行的系数乘上对应列标后的和就是\(A_i\)

于是我们发现了这一显然的规律

\[A_1 = 1,A_n = 2 A_{n-1} + n^k - (n-1)^k
\]

我们就非常优秀的把这个递推式化简了:p

2020/05/16 update

当时太菜了没学数列,实际上这个规律根本就不需要找,可以直接推出。

设 \(S_n = \sum_{i=1}^n a_n\) ,根据题意 \(a_n = S_{n-1} + n^k\) 。

用上式减去 \(a_{n-1} = S_{n-2} + (n+1)^k\) 得

\[\begin{aligned}
a_n - a_{n-1} &= a_{n-1} + n^k - (n+1)^k \\
a_n &= 2 a_{n-1} + n^k - (n+1)^k

\end{aligned}
\]

得到上式。

总感觉它有个通项公式什么的吧,我们来胡乱瞎推一波

观察递推式,右式那坨\(n^k - (n-1)^k\)看着就恶心,我们想找个办法把它消掉,使它的形式变成一个等比数列,这样通项公式就容易得到了

显然\(n^k - (n-1)^k\)是一个\(k-1\)次多项式,所以我们构造数列\(U\)和\(k-1\)次多项式\(B\)

\[\begin{aligned}
U_n = A_n + B(n) \\
B(n) = \sum_{i=0}^{k-1} b_i n^i
\end{aligned}
\]

对数列\(U\)的定义式移项得

\[A_n = U_n - B(n)
\]

带回\(A\)的递推式,得

\[\begin{aligned}
U_n - B(n) = 2(U_{n-1} - B(n-1)) + n^k - (n-1)^k \\
U_n = 2U_{n-1} + B(n) - 2B(n-1) + n^k - (n-1)^k
\end{aligned}
\]

我们想让\(U_n=2U_{n-1}\),只需使

\[B(n) - 2B(n-1) + n^k - (n-1)^k = 0
\]

\[- B(n) + 2B(n-1) = n^k - (n-1)^k
\]

现在我们要求解多项式\(B\),试着将多项式的每一项,也就是\(b_i\),都表示出来

先看右式,用二项式定理展开\((n-1)^k\),右式变为

\[\quad n^k - \sum_{i=0}^{k} C_k^i (-1)^{k-i} n^i
\]

提出和式中的\(k\)次项与\(n^k\)消掉

\[= - \sum_{i=0}^{k-1} C_k^i (-1)^{k-i} n^i
\]

再来看左式,将多项式展开得

\[- \sum_{i=0}^{k-1} b_i n^i + 2 \sum_{i=0}^{k-1} b_i (n-1)^i
\]

也用二项式定理展开\((n-1)^i\)

\[= - \sum_{i=0}^{k-1} b_i n^i + 2 \sum_{i=0}^{k-1} b_i \sum_{j=0}^i C_i^j (-1)^{i-j} n^j
\]

转换枚举

\[\begin{aligned}
&= - \sum_{i=0}^{k-1} b_i n^i + 2 \sum_{i=0}^{k-1} \sum_{j=0}^i b_iC_i^j (-1)^{i-j} n^j \\
&= - \sum_{i=0}^{k-1} b_i n^i + 2 \sum_{j=0}^{k-1} \sum_{i=j}^{k-1} b_iC_i^j (-1)^{i-j} n^j \\
&= - \sum_{i=0}^{k-1} b_i n^i + 2 \sum_{i=0}^{k-1} \{ \sum_{j=i}^{k-1} b_j C_j^i (-1)^{j-i} \} n^i
\end{aligned}
\]

(这里大括号只是为了标明系数,没有实际意义)

现在把左右式合在一起写

\[- \sum_{i=0}^{k-1} b_i n^i + 2 \sum_{i=0}^{k-1} \{ \sum_{j=i}^{k-1} b_j C_j^i (-1)^{j-i} \} n^i = - \sum_{i=0}^{k-1} C_k^i (-1)^{k-i} n^i
\]

消掉负号

\[\sum_{i=0}^{k-1} b_i n^i + 2 \sum_{i=0}^{k-1} \{ \sum_{j=i}^{k-1} b_j C_j^i (-1)^{j-i} \} n^i = \sum_{i=0}^{k-1} C_k^i (-1)^{k-i} n^i
\]

所以

\[b_i + 2 \sum_{j=i}^{k-1} b_j C_j^i (-1)^{j-i} = C_k^i (-1)^{k-i}
\]

于是我们非常愉快艰难的得到了\(b_i\)的表示,高斯消元即可得到\(b_i\)。

仔细观察发现这是个上三角矩阵,所以我们可以直接\(O(k^2)\)求解!

于是我们解出了多项式\(B\)。

回过头来看数列\(U\)的定义,\(U_n = A_n + B(n)\)

现在解出了\(B\),我们又知道\(A_1 = 1\),就能知道

\[U_1 = A_1 + B(1) = B(1) +1
\]

于是我们得到了数列\(U\)的完整递推式

\[U_1=B(1) + 1,U_n=2U_{n-1}
\]

现在就容易知道\(U\)的通项公式了,它是

\[U_n = ( B(1) + 1 )2^{n-1}
\]

又因为\(A_n = U_n - B(n)\),\(A\)的通项公式就出来了!

\[A_n = ( B(1) + 1 )2^{n-1} - B(n)
\]

完了

//洛谷P5364 [SNOI2017]礼物
//Author:sun123zxy
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<cstdlib>
#include<queue>
using namespace std;
typedef long long ll;
const ll MOD=1E9+7; ll QPow(ll x,ll up){//快速幂
x%=MOD;
ll ans=1;
while(up){
if(up%2==0){
x=x*x%MOD;
up/=2;
}else{
ans=ans*x%MOD;
up--;
}
}
return ans;
}
ll Inv(ll x){//逆元
return QPow(x,MOD-2);
} const ll MXK=2005;
ll fac[MXK],facInv[MXK];
void FacInit(ll n){
fac[0]=1;for(ll i=1;i<=n;i++) fac[i]=fac[i-1]*i%MOD;//求阶乘
facInv[n]=Inv(fac[n]);
for(ll i=n-1;i>=1;i--) facInv[i]=facInv[i+1]*(i+1)%MOD;//线性求阶乘逆元
facInv[0]=1;
}
ll C(ll n,ll k){//组合数
if(n<k) return 0;
return fac[n]*facInv[n-k]%MOD*facInv[k]%MOD;
} ll N,K;
ll c,B[MXK];//2^(n-1)的系数c和多项式B
ll GetY(ll x){//获取B(x)
x%=MOD;
ll y=0;
ll xPow=1;
for(int i=0;i<=K-1;i++){
y=(y+B[i]*xPow)%MOD;
xPow=xPow*x%MOD;
}
return y;
}
ll mtx[MXK][MXK];
void GetFormula(){
for(ll i=0;i<=K-1;i++) for(ll j=0;j<=K;j++) mtx[i][j]=0;
for(ll i=0;i<=K-1;i++){//初始化方程组
mtx[i][i]=1;
for(ll j=i;j<=K-1;j++){
ll p=-1;if((j-i)%2==0) p=1;
mtx[i][j]+=(-2*C(j,i)%MOD*p+MOD)%MOD;
}
ll p=-1;if((K-i)%2==0) p=1;
mtx[i][K]=(C(K,i)*p+MOD)%MOD;
}
for(ll i=K-1;i>=0;i--){//上三角高斯消元
B[i]=mtx[i][K]*Inv(mtx[i][i])%MOD;
for(ll j=i-1;j>=0;j--){
mtx[j][K]=(mtx[j][K]-B[i]*mtx[j][i]%MOD+MOD)%MOD;
mtx[j][i]=0;
}
}
c=(GetY(1)+1)+MOD%MOD;
}
int main(){
cin>>N>>K;
FacInit(K);
GetFormula();
cout<<(c*QPow(2,N-1)%MOD-GetY(N)+MOD)%MOD;
return 0;
}

和洛谷题解里rqy聚聚的解法似乎有一些关联(

2019/07/01

洛谷P5364 [SNOI2017]礼物 题解的更多相关文章

  1. 洛谷 P1194 买礼物 题解

    P1194 买礼物 题目描述 又到了一年一度的明明生日了,明明想要买\(B\)样东西,巧的是,这\(B\)样东西价格都是\(A\)元. 但是,商店老板说最近有促销活动,也就是: 如果你买了第II样东西 ...

  2. 洛谷P2832 行路难 分析+题解代码【玄学最短路】

    洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座 ...

  3. 【洛谷P3960】列队题解

    [洛谷P3960]列队题解 题目链接 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n×m ...

  4. 洛谷 P1194 买礼物

    洛谷 P1194 买礼物 题目描述 又到了一年一度的明明生日了,明明想要买B样东西,巧的是,这B样东西价格都是A元. 但是,商店老板说最近有促销活动,也就是: 如果你买了第II样东西,再买第J样,那么 ...

  5. 洛谷P2312 解方程题解

    洛谷P2312 解方程题解 题目描述 已知多项式方程: \[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0\] 求这个方程在 \([1,m]\) 内的整数解(\(n\) 和 \(m\) ...

  6. 洛谷P1577 切绳子题解

    洛谷P1577 切绳子题解 题目描述 有N条绳子,它们的长度分别为Li.如果从它们中切割出K条长度相同的 绳子,这K条绳子每条最长能有多长?答案保留到小数点后2位(直接舍掉2为后的小数). 输入输出格 ...

  7. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

  8. 洛谷 P1220 关路灯 题解

    Description 有 $n$ 盏路灯,每盏路灯有坐标(单位 $m$)和功率(单位 $J$).从第 $c$ 盏路灯开始,可以向左或向右关闭路灯.速度是 $1m/s$.求所有路灯的最少耗电.输入保证 ...

  9. 【洛谷P3410】拍照题解(最大权闭合子图总结)

    题目描述 小B有n个下属,现小B要带着一些下属让别人拍照. 有m个人,每个人都愿意付给小B一定钱让n个人中的一些人进行合影.如果这一些人没带齐那么就不能拍照,小B也不会得到钱. 注意:带下属不是白带的 ...

随机推荐

  1. c语言博客专业05

    问题 答案 这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-2/homework/8655 我在 ...

  2. Java 中 Snack3的使用

    网上看了一篇Java 中 Gson的使用,所以也跟着写篇Java 中 Snack3的使用 JSON 是一种文本形式的数据交换格式,从Ajax的时候开始流行,它比XML更轻量.比二进制容易阅读和编写:解 ...

  3. PHP的array_walk和array_map函数实现数组值UTF-8转GBK编码

    在PHP中,array_walk() 和 array_map()两个函数都可以实现对数组中每个值的修改,比如本例就是将数组中所有的值,由UTF-8编码转成GBK编码. 当然,除了这两个函数,也可以用 ...

  4. Python面试的一些心得,与Python练习题分享【华为云技术分享】

    版权声明:本文为CSDN博主「华为云」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/devcloud/arti ...

  5. 简单理解http协议的特性

    http协议一种数据传输的规范,像我们的在发送数据的时候,我们无法保证发送与接收的类型是一致的,它就保证了我们传输的同一个类型数据. 特性: 1.灵活:我们不管传输什么数据,图片,文件,文字,都可以进 ...

  6. Objective-C面试题(精心整理的,附答案)

    转自:http://www.mianwww.com/html/2014/03/20372.html 1.objective-c 是所有对象间的交互是如何实现的? 在对象间交互中每个对象承担的角色不同, ...

  7. linux gre隧道创建

    目录 linux gre隧道创建 实验环境 实验目的 实验步骤 1.在host A(10.10.10.47)上面操作 2.在host B(192.168.0.118)上面操作 实验结果 还原实验环境 ...

  8. WebGPU学习(五): 现代图形API技术要点和WebGPU支持情况调研

    大家好,本文整理了现代图形API的技术要点,重点研究了并行和GPU Driven Render Pipeline相关的知识点,调查了WebGPU的相关支持情况. 另外,本文对实时光线追踪也进行了简要的 ...

  9. 从零开始的openGL——四、纹理贴图与n次B样条曲线

    前言 在上篇文章中,介绍了如何加载绘制模型以及鼠标交互的实现,并且遗留了个问题,就是没有模型表面没有纹理,看起来很丑.这篇文章将介绍如何贴纹理,以及曲线的绘制. 纹理贴图 纹理加载 既然是贴图,那首先 ...

  10. Mybatis获取自动增长Id

    Mybatis获取自动增长Id MyBatis成功插入后获取自动增长的id 1.向xxMapping.xml配置中加上两个配置. <insert id="insertUser" ...