幼儿园数学题II

幼儿园数学题II

\(Time\) \(Limit:10000MS\)\(Memory\) \(Limit:65536K\)\(Case\) \(Time\) \(Limit:1000MS\)

Description

这天,当一头雾水的LZH同学在考场上痛哭的时候,一旁的YMW早就如切菜一样cut掉了简单至极的第一题,风轻云淡的冲击着满分,然而最后一道题着实难道了他,毕竟是幼儿园副园长树皮和著名毒瘤秋彪为了防止人AK而出的,可是YMW作为ACrush的著名粉丝,向来以AK为目标,永不言败,而他能不能AK就看你了
题目是酱紫的,\(f(n)-f(3)-f(4)-f(5)-...-f(n-3)-f(n-2)=(n+4)(n-1)/2,f(1)=1,f(2)=1\)
\(f(n)\)的前\(n\)项和

Input

输入 一个正整数n(保证\(0<=n<=2^{31}-1\))

Output

输出 一个正整数,表示前\(n\)项之和,需要对\(1000000007\)求余

Sample Input

样例输入1

1

样例输出1

1

样例输入2

2

样例输出2

2

分析:

原式化为:

\[f_n=(n+4)(n-1)/2+f_3+f_4+f_5+...+f_{n-3}+f_{n-2} \]

再把\((n+4)(n-1)/2\) 展开 得到\((n^2+3n-4)/2\) 化为\(n^2/2+3n/2-2\)
带入原式:$$f_n=f_3+f_4+f_5+...+f_n-3+f_{n-2}+n^2/2+3n/2-2$$
我们再对比\(f_{n+1}\)同理可得:

\[f_{n+1}=f_3+f_4+f_5+...+f_{n-3}+f_{n-2}+f_{n-1}+(n+1+4)(n+1-1)/2 \]

\((n+1+4)(n+1-1)/2\) 化为\([(n+5)n]/2\) 得出\(n^2/2+5n/2\)
带入原式

\[f_{n+1}=f_3+f_4+f_5+...+f_{n-3}+f_{n-2}+f_{n-1}+n^2/2+5n/2 \]

\(f_{n+1}\)相比\(f_n\) 多出了\(f_{n-1}+n+2\)\(∴f_{n+1}\)就等于\(f_{n}+f_{n-1}+n+2\) 也等于\(f_n+f_{n-1}+(n+1)+1\)那么

\[f_n=f_{n-1}+f_{n-2}+n+1 \]

得出这个结论后 我们直接做矩阵乘法即可 与之前一道例题类似
具体思路:\(link\)

CODE:

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
const int mod=1e9+7;
long long n;
using namespace std;
struct matrix{
	long long n,m;
	long long F[11][11];
}A,B,C;
matrix operator *(matrix A,matrix B){
	matrix C;
	C.n=A.n,C.m=B.m;
	for(int i=1;i<=C.n;i++)
		for(int j=1;j<=C.m;j++)
			C.F[i][j]=0;
	for(int k=1;k<=A.m;k++)
		for(int i=1;i<=C.n;i++)
			for(int j=1;j<=C.m;j++)
				C.F[i][j]=(C.F[i][j]+(A.F[i][k]*B.F[k][j])%mod)%mod;
	return C;
}
void ksm(long long x){
	if(x==1){
		B=A;
		return; 
	}
	ksm(x>>1);
	B=B*B;
	if(x&1) B=B*A;
}
int main(){
	scanf("%lld",&n);
	if(n==1){
		printf("1");
		return 0;
	}
	A.n=5,A.m=5;
	A.F[1][1]=0,A.F[1][2]=1,A.F[1][3]=0,A.F[1][4]=0,A.F[1][5]=0;
	A.F[2][1]=1,A.F[2][2]=1,A.F[2][3]=1,A.F[2][4]=0,A.F[2][5]=0;
	A.F[3][1]=0,A.F[3][2]=0,A.F[3][3]=1,A.F[3][4]=0,A.F[3][5]=0;
	A.F[4][1]=0,A.F[4][2]=1,A.F[4][3]=0,A.F[4][4]=1,A.F[4][5]=0;
	A.F[5][1]=0,A.F[5][2]=1,A.F[5][3]=0,A.F[5][4]=1,A.F[5][5]=1;
	ksm(n-1);
	C.n=1,C.m=5;
	C.F[1][1]=1,C.F[1][2]=1,C.F[1][3]=1,C.F[1][4]=3,C.F[1][5]=1;
	C=C*B;
	printf("%lld",C.F[1][3]);
	return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
洛谷P2791是一道关于幼儿园篮球的题目。题目描述如下: 在幼儿园里,小朋友们正在进行篮球比赛。每个小朋友都有一个篮球,他们按照顺序依次投篮。每个小朋友投篮时,可以选择将篮球投给左边的小朋友或者右边的小朋友。每个小朋友投篮得分的规则如下: 1. 如果一个小朋友左右两边的小朋友都没有投篮过,那么他的得分为1; 2. 如果一个小朋友左边的小朋友投篮过,但右边的小朋友没有投篮过,那么他的得分为左边小朋友的得分加1; 3. 如果一个小朋友右边的小朋友投篮过,但左边的小朋友没有投篮过,那么他的得分为右边小朋友的得分加1; 4. 如果一个小朋友左右两边的小朋友都投篮过,那么他的得分为左边小朋友和右边小朋友得分的最大值加1。 现在给定每个小朋友投篮的顺序,请你计算每个小朋友的得分。 例如,给定投篮顺序为[1, 0, 1, 0, 1],则第一个小朋友的得分为1,第二个小朋友的得分为2,第三个小朋友的得分为1,第四个小朋友的得分为2,第五个小朋友的得分为1。 你可以通过编写程序来解决这个问题。具体的解题思路可以参考以下步骤: 1. 创建一个数组scores,用来存储每个小朋友的得分; 2. 遍历投篮顺序数组,对于每个小朋友,根据上述规则计算他的得分,并将得分存入scores数组中; 3. 最后输出scores数组即可。 希望以上解答对你有帮助!如果你还有其他问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值