Comet OJ 计算机(computer)

Comet OJ 计算机(computer)

题目传送门

题目描述

小 X 有一台奇怪的计算机。

这台计算机首先会读入一个正整数 nn,然后生成一个包含 nn 个数的序列 aa

一开始 a_i(1 \le i \le n)*a**i(1≤in*) 的值均为 11。

接下来,小 X 会进行 n-1n−1 次操作,每次操作会输入一个指令,这个指令有 22 种情况:

  1. x +表示把此时序列中第 xx 个数 a_x*a**x* 和第 x+1x+1 个数 a_{x+1}ax+1 合并为一个数,值为 a_x + a_{x+1}ax+*a**x*+1。
  2. x *表示把此时序列中第 xx 个数 a_x*a**x* 和第 x+1x+1 个数 a_{x+1}ax+1 合并为一个数,值为 a_x \times a_{x+1}ax×*a**x*+1。

假设某个时刻序列中元素的个数为 kk,小 X 必须保证 1 \le x < k1≤x<k

那么,经过 n-1n−1 次操作后,序列只剩下了一个数,此时计算机会输出这个数。

小 X 想知道,当他输入 nn 时,这台计算器输出的数最大会是多少。

由于这个数可能会很大,你只需要求出这个数模 10^9+7109+7 的值。

输入描述

一行一个正整数 nn

输出描述

一行一个整数,表示答案对 10^9+7109+7 取模后的值。

样例输入 1

6

样例输出 1

9

样例解释 1

一开始的序列为1 1 1 1 1 1

小 X 的操作指令如下:

1.1 +序列变为2 1 1 1 1

2.1 +序列变为3 1 1 1

3.2 +序列变为3 2 1

4.2 +序列变为3 3

5.1 *序列变为9

可以证明没有操作指令可以使计算机输出的数大于 99。

样例输入 2

37

样例输出 2

708588

提示

【数据范围与提示】

对于 10%10% 的数据,1 \le n \le 21≤n≤2。

对于 25%25% 的数据,1 \le n \le 101≤n≤10。

对于 40%40% 的数据,1 \le n \le 1001≤n≤100。

对于 55%55% 的数据,1 \le n \le 10001≤n≤1000。

对于 70%70% 的数据,1 \le n \le 10^61≤n≤106。

对于 85%85% 的数据,1 \le n \le 10^91≤n≤109。

对于 100%100% 的数据,1 \le n \le 10^{18}1≤n≤1018。

题解:

一道数学题。

我喜欢把这种题叫做数列操作题。一般来讲,这种题不是DP就是数学推导。针对于这道题来讲,我们无法设计DP,只能使用我们的脑袋瓜子进行数学问题的分析和推导。

首先,我们初始的数列全都是1,我们在此基础上进行数列合并操作。那么题意可以转化为,给定\(n\),让你把\(n\)分解成若干个整数,使得其乘积最大。

然后我们进行模拟拆分,我们会发现,针对一个1 1 1 1的串,我们可以直接把它合成4,也可以把它拆成\(2\times 2\),最后也得4。但是,如果针对一个长度比4还大的串,比如1 1 1 1 1,我们如果直接加的话,就是5,而进行合并成\(2\times 3\)的话,就会出现6的答案。也就是说,针对一个全由1组成的串中长度大于4的字串,我们把它拆成由一群2和一群3的乘积的做法对后来的答案总是贡献最大的。

也就是说,原题的目的就可以被我们搞成\(2^a\times 3^b\).我们很容易得出,拆出的3越多越好。

这样的话,我们用\(n\)模3,如果余数为0,那么就直接输出\(3^{\frac{n}{3}}\).如果余数为1,那么我们就拆成\(2\times 2\times 3^{\frac{n-4}{3}}\),如果余数为2,就直接拆成\(2\times 3^{\frac{n-2}{3}}\)

注意特盘答案为1和指数为1的情况,记得每一步都要取模,以及开Longlong,本题可A/

求幂的操作一定要用快速幂,要不然肯定会T啊。

如果不会快速幂的话...

请参考以下的博客:

浅谈快速幂

代码如下:

#include<cstdio>
#define ll long long
using namespace std;
const ll mod=1e9+7;
ll n;
ll qpow(ll a,ll b)
{
    ll ret=1;
    if(!b)
        return 1;
    while(b>0)
    {
        if(b&1)
            ret=(ret*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ret%mod;
}
int main()
{
    scanf("%lld",&n);
    if(n==1)
    {
        printf("1");
        return 0;
    }
    if(n%3==0)
    {
        ll p=n/3;
        printf("%lld",qpow(3,p));
    }
    else if(n%3==1)
    {
        ll p=(n-4)/3;
        printf("%lld",(4*qpow(3,p))%mod);
    }
    else
    {
        ll p=(n-2)/3;
        printf("%lld",(2*qpow(3,p))%mod);
    }
    return 0;
}

转载于:https://www.cnblogs.com/fusiwei/p/11602071.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值