M≡N(modP)同余这一属性看起来简单,然而却是数论中极为重要的概念。与之相关的公式和定理更是纷繁芜杂,如果不是数学背景的童鞋,恐怕很难深入去钻研所有的知识。我们这一篇作为一个简单的入门,用同余公式来解决一个阶乘问题。在做题之前,先来熟悉一个"/>

四两拨千斤,GCC编译器(同余模) - HDU 3123

Posted ACM算法日常

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四两拨千斤,GCC编译器(同余模) - HDU 3123相关的知识,希望对你有一定的参考价值。

对于两个数M和N,如果M%P == N%P,则可以说M和N对P同余。记作公式:

同余这一属性看起来简单,然而却是数论中极为重要的概念。与之相关的公式和定理更是纷繁芜杂,如果不是数学背景的童鞋,恐怕很难深入去钻研所有的知识。


我们这一篇作为一个简单的入门,用同余公式来解决一个阶乘问题。在做题之前,先来熟悉一个简单的公式:

( M + N ) % P = ( M % P + N % P ) % P


这个公式简单的说就是模运算的分配律,感性的可以认为,M对P的余数X,以及N对P的余数Y,两者相加X+Y可能大于P,所以单独取余相加后要再取一次余,保证结果不大于P。也正是该式子,能够轻易解决下题中的一个阶乘问题。


所谓取余取余,就是不断地减去整的,留下余的罢。


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

gcc编译器是GNU项目组的开发的一个编译系统,支持多种编程语言。但是gcc不支持阶乘符号!。对于表达式n!,它表示从1乘到n的一个值。比如4! = 4x3x2x1 = 24。0的阶乘为1,表示不乘以任何值。


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.

第一行表示测试用例个数T

后面每行包含2个整数n和m


Output

Output the answer of (0! + 1! + 2! + 3! + 4! + ... + n!)%m.
输出 (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


这道题就是上面公式的典型应用,对于一个阶乘n!来说,如果m<n,则必有:n! % m = 0


也就是说,n!对所有小于等于n的数取模都是0。


数学最大的特点之一就是喜欢说废话,而且还要证明。


通过取余避免了大数运算,另外本题精巧之处还在于在一次for循环中计算了从阶乘1!、2!一直到(m-1)!的和。


本文隶属于算法合集中的一篇,更多内容可以通过菜单栏点击算法合集查看~


源代码:GCC

#include <stdio.h>
#include <stdint.h>

int main()
{
    int count;
    scanf("%d", &count);

    int64_t ans;
    int64_t futher, num, mod;

    char nstr[200];

    while (count--)
    {
        scanf("%s", nstr);
        scanf("%I64d", &mod);

        //公式: (a+b)%c=(a%c+b%c)%c
        //可以知道 m!+(m+1)!….n!这一些对m取余都是0,所以就不需考虑了。
        //所以判断n和m的大小,取较小值。
        if (strlen(nstr) >= 7)
            num = 1000000;
        else
            sscanf(nstr, "%I64d", &num);

        if (num > mod)
            num = mod;

        futher = 1;
        ans = 1;

        for (int i = 1; i <= num; i++)
        {
            futher = (futher * i) % mod;
            //如果能够整除mod,说明后面的数都可以整除mod,不需要再计算
            if (futher == 0)
                break;
            //每次将模加入到ans中
            ans += futher;
        }

        printf("%I64d\n", ans % mod);
    }
    return 0;
}

温馨提示




点赞的时候,请宠溺一点


以上是关于四两拨千斤,GCC编译器(同余模) - HDU 3123的主要内容,如果未能解决你的问题,请参考以下文章

POJ - 2635 The Embarrassed Cryptographer(千进制+同余模)

The Embarrassed Cryptographer POJ - 2635 同余模+高精度处理 +线性欧拉筛(每n位一起处理)

POJ 1426 Find The Multiple &amp;&amp; 51nod 1109 01组成的N的倍数 (BFS + 同余模定理)

HDU 5974 A Simple Math Problem ——(数论,大连区域赛)

同余HDU 6108 小C的倍数问题

hdu2815-Mod Tree高次同余方程-拓展BadyStepGaintStep