H胖胖的健身计划
时间: 1ms 内存:128M
描述:
L老师布置了一道思考题,一个人一次可以上一个台阶,也可以上两个台阶,问上到n级台阶有多少种走法?H胖胖非常聪明,拿出胖胖的小手掐指算起来。登上第一级台阶有一种登法;登上两级台阶,有两种登法;登上三级台阶,有三种登法;登上四级台阶,有五种方法……所以,1,2,3,5,8,13,……。
H胖胖为了保持身体苗条,给自己制定了一个锻炼计划,决定用刚才计算的数列确定每天自己锻炼的步数,就是说第1天走1步,第2天走2步,第3天走5步,第4天走8步,第5天走13步,……。
H胖胖的同学LYQ正好在学习矩阵相乘,帮他想到了一个快递计算的方法如下公式所示。
H胖胖拿出手机查阅了快速幂的百度百科,看到如下信息:
快速幂
顾名思义,快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高。
原理
以下以求a的b次方来介绍:
把b转换成二进制数。
该二进制数第i位的权为
例如
11的二进制是1011
11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1
因此,我们将a¹¹转化为算
但是H胖胖的手机太不给力,后面的代码实在看不清了,请正在做题的你帮帮他吧。
输入:
一个整数n(0<n<10^12)
输出:
H胖胖走的步数%100007的结果
示例输入:
6
示例输出:
13
提示:
参考答案(内存最优[1120]):
#include<stdio.h>
#define mod 100007
typedef struct matrix
{
long long a1,a2,a3,a4;
matrix operator * (const matrix& w)
{
matrix res;
res.a1=(a1*w.a1%mod+a2*w.a3%mod)%mod;
res.a2=(a1*w.a2%mod+a2*w.a4%mod)%mod;
res.a3=(a3*w.a1%mod+a4*w.a3%mod)%mod;
res.a4=(a3*w.a2%mod+a4*w.a4%mod)%mod;
return res;
}
};
long long qpow(long long n)
{
matrix base;
matrix ans;
ans.a1=ans.a2=ans.a4=1;
ans.a3=0;
base.a1=base.a2=base.a3=1;
base.a4=0;
while(n){
if(n&1)ans=base*ans;
base=base*base;
n>>=1;
}
return ans.a1;
}
int main()
{
//freopen("in8.txt","r",stdin);
//freopen("out8.txt","w",stdout);
long long n=0;
long long ans=0;
scanf("%lld",&n);
ans=qpow(n);
printf("%lld\n",ans);
}
参考答案(时间最优[2]):
#include <iostream>
#include <math.h>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
const long long mod = 100007;
struct node {
long long mp[2][2];
void init(long long a, long long b, long long c, long long d) {
mp[0][0] = a;
mp[0][1] = b;
mp[1][0] = c;
mp[1][1] = d;
}
void mult(node x, node y) //两矩阵乘法
{
memset(mp, 0, sizeof(mp));
for (long long i = 0; i < 2; i++)
for (long long j = 0; j < 2; j++)
for (long long k = 0; k < 2; k++)
mp[i][j] = (mp[i][j] + x.mp[i][k] * y.mp[k][j]) % mod;
};
} init;
struct node expo(struct node x, long long k) //进行k次幂运算
{
struct node tmp;
tmp.init(1, 0, 0, 1); //单位矩阵
while (k) //快速幂部分
{
if (k & 1)
tmp.mult(tmp, x);
x.mult(x, x);
k >>= 1;
}
return tmp;
}
int main() {
#ifdef LOCAL_IM0QIANQIAN
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif // LOCAL_IM0QIANQIAN
long long k;
scanf("%lld", &k);
init.init(1, 1, 1, 0); //初始化矩阵(1 1 1 0)
printf("%lld\n", expo(init, k+1).mp[0][1] % mod);
return 0;
}
题目和答案均来自于互联网,仅供参考,如有问题请联系管理员修改或删除。