最近碰到一题,问你求mod (p1*p2*p3*……*pl) ,其中n和m数据范围是1~1e18 , l ≤10 , pi ≤ 1e5为不同的质数,并保证M=p1*p2*p3*……*pl ≤ 1e18 。

要解决这个问题首先需要Lucas定理 或者 C!解法。

Lucas定理

我们令n=sp+q , m=tp+rq , r ≤ p

那么,然后你只要继续对调用Lucas定理即可。

代码可以递归的去完成这个过程,其中递归终点为t = 0

伪代码,时间O(logp(n)*p)

int Lucas (ll n , ll m , int p) {
return m == 0 ? 1 : 1ll*comb (n%p , m%p , p) * Lucas (n/p , m/p , p) % p ;
}
//comb()函数中,因为q , r ≤ p , 所以这部分暴力完成即可。

 Lucas定理证明:

证明资料:http://www.cut-the-knot.org/arithmetic/algebra/LucasTheorem.shtml

首先你需要这个算式:,然后

(1 + x) n Ξ (1 + x) sp+q  Ξ ( (1 + x)p)s • (1 + x) q Ξ (1 + xp) s • (1 + x)   (mod p) ;

.

所以,通过左右系数比较,你就会发现当i=t , j=r  (及xtp+r的系数等式)成立。

 

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5446

#include<bits/stdc++.h>
using namespace std;
typedef long long ll ;
const int M = 1e5 + 10 ;
ll n , m ;
int k ;
int prime[15] ;
int rem[15] ; ll MM ; int F[15] ;
//int Finv[15][M] , F[15][M] , inv[15][M] ; ll mul (ll a , ll b , ll mod) {
ll tmp = 0 ;
while (b) {
if (b & 1) tmp = (1ll*tmp+a)%mod ;
b >>= 1 ;
a = (a+a)%mod ;
}
return tmp ;
} int Fermat (ll a , int b) {
int ret = 1 ;
int mod = b ;
b -= 2 ;
while (b) {
if (b & 1) ret = mul(ret , a , mod) ;
b >>= 1 ;
a = mul(a , a , mod) ;
}
return ret ;
} int fact (int n , int p) {
int ret = 1 ;
for (int i = 1 ; i <= n ; i ++) ret = 1ll*ret*i%p ;
return ret ;
} int comb (int n , int m , int p) {
if (m < 0 || m > n) return 0 ;
return 1ll* fact (n , p) * Fermat(fact (m , p) , p) * Fermat (fact(n-m , p) , p) % p ;
} int Lucas (ll n , ll m , int p) {
return m == 0 ? 1 : 1ll*comb (n%p , m%p , p) * Lucas (n/p , m/p , p) % p ;
} void solve () {
MM = 1 ;
for (int i = 1 ; i <= k ; i ++) {
rem[i] = Lucas (n , m , prime[i]) ;
MM *= 1ll*prime[i] ;
//cout << "rem[i] = " << rem[i] << endl;
}
ll sum = 0 ;
for (int i = 1 ; i <= k ; i ++) {
ll tmp = MM/prime[i] ;
ll ans = mul (rem[i] , Fermat(tmp , prime[i]) , MM) ;
sum = (sum + mul (ans , tmp , MM) ) % MM ;
}
printf ("%I64d\n" , sum);
} int main () {
int T ;
scanf ("%d" , &T) ;
while (T --) {
scanf ("%I64d%I64d%d\n" , &n , &m , &k) ;
for (int i = 1 ; i <= k ; i ++) {
scanf ("%d" , &prime[i]) ;
}
solve () ;
}
return 0 ;
}

最新文章

  1. Django进阶(三)
  2. javascript 原型及原型链的初步理解
  3. 如何将动态生成Word文件
  4. 深入理解ASP.NET 5的依赖注入
  5. 面试知识点总结之Java语言
  6. img图片放大控件 lightbox.js
  7. Provides PHP completions for Sublime Text
  8. 关于在TP的各类标签中的注意事项
  9. loadview 方法调用
  10. HDU 4497 数论+组合数学
  11. [HDOJ5521]Meeting(最短路)
  12. -webkit-text-size-adjust: none;该如何处理
  13. php之文件上传类代码
  14. lua本学习笔记功能
  15. 订单处理(c#实现)
  16. h5可预览 图片ajax上传 ,后台有点弱不知道数据怎么取,但是可以肯定数据上传成功了
  17. html css笔记zht
  18. linux驱动编写(pwm驱动)【转】
  19. TCP/IP详解 卷1 第十八章 TCP的建立与终止
  20. STL基础1:vector

热门文章

  1. Linux 内核进程管理之进程ID
  2. Java程序设计之裴波拉切那数列(兔子一年的数量)
  3. webService获取电话号归属地和获取天气情况步骤,及创建属于自己的webservice
  4. android:exported 属性详解
  5. Object.assign方法复制或合并对象
  6. 国内外前端(js)开发框架对比
  7. Log4j的ConversionPattern参数的格式含义
  8. js的this和面向对象编程
  9. linux/ubuntu查看内核版本命令
  10. jsp项目部署