大意:给一个n,一个m,求(0! + 1! + 2! + 3! + 4! + ... + n!)%m 0 <= n < 10^100 0 < m < 1000000
思路:n可以达到10^100,很明显不能直接处理。但是发现只要n>m,那么m!+(m+1)!+...+n!这些项都是可以被m整除的,要对m求余,只需要找比m小的阶乘即可,而m的范围为1000000,在O(m)的复杂度下是可以完成的。所以只需判断n是否大于m,若大于m,则取m-1即可,若小于m则不变。
1 #include <map> 2 #include <queue> 3 #include <stack> 4 #include <math.h> 5 #include <stdio.h> 6 #include <string.h> 7 #include <iostream> 8 #include <algorithm> 9 #define LL long long 10 using namespace std; 11 12 void run() 13 { 14 int n, m; 15 char s[1010]; 16 scanf("%d", &n); 17 while(n--) 18 { 19 int t = 0; 20 scanf("%s%d%*c", s, &m); 21 ///输入可能是很大的数据(10^100)所以要用字符串处理 22 int len = strlen(s); 23 if(len >= 7) ///判断输入是否大于1000000 24 t = m-1; 25 else 26 { 27 int p = 1; 28 for(int i = len-1; i >= 0; i--) 29 { 30 t += (s[i]-'0')*p; 31 p *= 10; 32 } 33 } 34 if(t >= m) 35 t = m-1; 36 LL temp = 1, ans = 1; 37 for(LL i = 1; i <= t; i++) ///处理阶乘之和 38 { 39 temp = (temp*i)%m; 40 ans = (ans+temp)%m; 41 } 42 ans %= m; 43 printf("%lld ", ans); 44 } 45 } 46 47 int main(void) 48 { 49 run(); 50 51 return 0; 52 }
同余定理:
1)a≡a(mod d)
2)a≡b(mod d)→b≡a(mod d)
3)(a≡b(mod d),b≡c(mod d))→a≡c(mod d)
如果a≡x(mod d),b≡m(mod d),则
4)a+b≡x+m (mod d)
5)a-b≡x-m (mod d)
6)a*b≡x*m (mod d )
7)a≡b(mod d)则a-b整除d
同余定理具有可加、可减、可乘、乘方性:
(A + B) % C = (A % C + B % C) % C;
(A - B) % C = (A % C - B % C) % C;
(A * B) % C = (A % C * B % C) % C;
(A ^ B) % C = (A^N + B^N) % C;
注:写的时候脑残了,感谢大神的指教,感谢!