西南科技大学2021届新生赛--F.数字金字塔(java大数、矩阵快速幂)

链接:https://ac.nowcoder.com/acm/contest/12478/F
来源:牛客网

现在有一个数字金字塔,它的第1层有1个数字1,第2层有3个数字2,……,第i层有2i−1个数字i,形如:

现在我们希望你能够求从第1层到第n层的数字和。由于答案可能过大,输出对998244353取模的结果。

思路:联想到数列问题。可以转化为求和,即通项为(2i-1)*i的数列的前n项和。通过对式子整理发现,原式子可以转换为:2i^{^{2}}-i,则i的前n项和很容易求出,那么对i^{^{^{2}}}求和公式如下:

\frac{2n^{_{3}}+3n_{2}+n}{6},则通过整理以后,我们可以求出题目中前n项和的表达式为:

                                                                            n(n+1)(2n+1)\times 3^{mod-2}-n(n+1)\times 2^{mod-2}

因此,使用O(1)的时间复杂度即可解决问题。

代码1:

使用Java大数解决:

import java.math.BigInteger;
import java.util.Scanner;

/**
 * @author Deng Huawei
 * @create 2021-03-20 16:24
 */
public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int T = scan.nextInt();
        while (T!=0)
        {
            T--;
            int n = scan.nextInt();
            BigInteger nn = BigInteger.valueOf(n);
            BigInteger aa = BigInteger.valueOf(4);
            BigInteger dd = BigInteger.valueOf(6);
            aa = aa.multiply(nn);
            aa = aa.multiply(nn);
            aa = aa.multiply(nn);
           // System.out.println(aa);
            BigInteger bb = BigInteger.valueOf(3);
            bb = bb.multiply(nn);
            bb = bb.multiply(nn);
          //  System.out.println(bb);
            aa = aa.add(bb);
            aa = aa.subtract(nn);
            aa = aa.divide(dd);
            BigInteger m = BigInteger.valueOf(998244353);
            System.out.println(aa.mod(m));
        }
    }
}

代码2:

使用矩阵快速幂解决:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int mod=998244353;
    ll poww(ll a,ll b)
    {
        ll res=1;
        while(b)
        {
            if(b&1)
            {
                res=res*a%mod;
            }
            a=a*a%mod;
            b>>=1;
        }
        return res%mod;
    }
    int main()
    {
        int T;
        int n;
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d",&n);
            ll ans = poww(3,mod-2)%mod*n%mod*(n+1)%mod*(2*n%mod+1)%mod;
            ll ans2 = poww(2,mod-2)%mod*n%mod*(n+1)%mod;
            ll last_answer = ans-ans2;
            cout<<(last_answer%mod+mod)%mod<<endl;
        }
        system("pause");
        return 0;
    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值