题目 2587: 八次求和

题目

给定正整数 n,求 (18+28+…+n8) mod 123456789。其中 mod 表示取余。

输入
输入的第一行包含一个整数 。

输出
输出一行,包含一个整数,表示答案。

样例输入
2

样例输出
257

提示
对于 20% 的评测用例,1 ≤ n ≤ 20 。
对于 60% 的评测用例,1 ≤ n ≤ 1000 。
对于所有评测用例,1 ≤ n ≤ 1000000 。

解题思路

由题目可知,本题的数据范围可能很大,因此需要设置为int类型,其次,尽可能多次取余,让更小的余数相乘,而不是让大数相乘。

难点

  1. 取余具有加法、乘法的分配、交换律,如下:
    (A+B)%C = (A%C+B%C)%C
    (A*B)%C = ((A%C)*(B%C))%C;
  2. 赋值符号的右边,如果是A*B的形式,那么A会“暂存”结果,再赋值给等号左边,这一理解关系到A的取值范围的设定(比如,i 应当设定为long int类型);
  3. 做题过程中错误分析,试图一步到位计算4次、8次:
temp = i*i%M;
a+=((temp*temp)%M*(temp*temp)%M)%M;

看似上述代码和正确代码中的如下部分一致,但是上述代码实际是将“4次取模先乘以4次,再取模(即先算(temptemp)%M(temp*temp),会越界)”,下部分代码是“先获得4次取模,再以‘4次取模’相乘获得8次的值”:

temp = i*i%M;
temp = (temp*temp)%M;
temp = (temp*temp)%M;

以上三行代码也等价于(和错误代码相差表优先顺序的括号):

temp = i*i%M;
temp = ((temp*temp)%M)*((temp*temp)%M)%M;

代码

#include<stdio.h>
#define M 123456789

int main()
{
    int n;
    long int i,temp;
    long int a=1;
    scanf("%d",&n);
    for (i=2;i<=n;i++)
    {
        temp = i*i%M;
        temp = (temp*temp)%M;
        temp = (temp*temp)%M;
        a+=temp;
        a%=M;
    }
    printf("%ld",a);
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值