hdu3123--阶乘和的处理方法

本文介绍了一道关于GCC编译器的编程挑战题,任务是计算一系列阶乘的和并对特定数取余。文章分析了解题思路,并给出了两种高效的算法实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



GCC

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 5140    Accepted Submission(s): 1716


Problem Description
The GNU Compiler Collection (usually shortened to GCC) is a compiler system produced by the GNU Project supporting various programming languages. But it doesn’t contains the math operator “!”.
In mathematics the symbol represents the factorial operation. The expression n! means "the product of the integers from 1 to n". For example, 4! (read four factorial) is 4 × 3 × 2 × 1 = 24. (0! is defined as 1, which is a neutral element in multiplication, not multiplied by anything.)
We want you to help us with this formation: (0! + 1! + 2! + 3! + 4! + ... + n!)%m
 

Input
The first line consists of an integer T, indicating the number of test cases.
Each test on a single consists of two integer n and m.
 

Output
Output the answer of (0! + 1! + 2! + 3! + 4! + ... + n!)%m.

Constrains
0 < T <= 20
0 <= n < 10^100 (without leading zero)
0 < m < 1000000
 

Sample Input
      
1 10 861017
 

Sample Output
      
593846
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   3125  3127  3126  3124  3118 
思路:
这道题的数据是10的100次方,数据大的让我比赛的时候就选择性放弃了。。。。
其实这道题不难,这道题就是求阶层和取余,因为(a+b)%m=(a%m)+(b%m),因为取余的m较小,根据公式又知道大于等于m的阶乘一定为0,
所以最大只需要算到m-1位就行,所以这个题目就简单了。
下面给出两种求连续阶乘和的O(n)算法。
1.(1!+2!+...+n!) 可以化解为1+1*(1+2*(1+3*(1+4*(1+5(.....(n-1)*(n)))))) ;如果不理解就直接记住。
2.如果要算1到k的阶乘和
for(sum=1,j=1,i=1;i<=k;i++)
   {
         j=j*i%m;
          sum=(sum+j)%m;
   }
因为j虽然只从1乘到了k,但是sum每次加上的都是j的阶乘,这样就不用去写双循环了。
我的代码用的是第一种方法,两种都可。
#include<stdio.h>
#include<iostream>
#include<cstring>
using namespace std;
char a[102];
int main()
{
    int t;
    long long m,ans;
    scanf("%d",&t);
    while(t--)
    {
        ans=0;
        scanf("%s",a);
        scanf("%lld",&m);
        //cout<<a<<endl;
       long long sum=0;
        int len=strlen(a);
        //cout<<len<<endl;
        for(int i=0;i<len;i++)
        {
           sum=sum*10+(a[i]-'0');
           if(sum>m)    break;
          // cout<<sum<<endl;
        }
        //cout<<sum<<endl;
        if(sum>=m)
        {
            ans=m-1;
            for(int i=ans-1;i>=1;i--)   ///    (1!+2!+...+n!)可以化解为1+1*(1+2*(1+3*(1+4*(1+5(.....(n-1)*(n)))))) ;
            {
               ans=(((ans+1)%m)*i%m)%m;
            }
        }
        else
        {
            ans=sum;
            for(int i=ans-1;i>=1;i--)   ///    (1!+2!+...+n!)可以化解为1+1*(1+2*(1+3*(1+4*(1+5(.....(n-1)*(n)))))) ;
            {
               ans=(((ans+1)%m*i%m))%m;
            }
        }
        printf("%lld\n",(ans+1)%m);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值