Lucas+中国剩余定理 HDOJ 5446 Unknown Treasure
2024-08-30 14:55:39
题意:很裸,就是求C (n, m) % (p1 * p2 * p3 * .... * pk)
分析:首先n,m<= 1e18, 要用到Lucas定理求大组合数取模,当然p[]的乘积<=1e18不能直接计算,但是pi<=1e5。接下来要知道中国剩余定理,所以先对每个pi计算出bi,注意在中国剩余定理的两数相乘会爆long long,所以用乘法取模,"但是这样的话exgcd返回值如果是负数就会出错,所以乘之前要取模成正的",这句话不是很懂。
收获:老祖宗的智慧结晶一定要学
代码:
/************************************************
* Author :Running_Time
* Created Time :2015/9/15 星期二 13:40:41
* File Name :J.cpp
************************************************/ #include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std; #define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
ll f[N]; void init(int p) {
f[0] = 1;
for (int i=1; i<=p; ++i) f[i] = f[i-1] * i % p;
} ll pow_mod(ll a, ll x, ll p) {
ll ret = 1;
while (x) {
if (x & 1) ret = ret * a % p;
a = a * a % p;
x >>= 1;
}
return ret;
} ll Lucas(ll n, ll k, ll p) { //C (n, k) % p
ll ret = 1;
while (n && k) {
ll nn = n % p, kk = k % p;
if (nn < kk) return 0;
ret = ret * f[nn] * pow_mod (f[kk] * f[nn-kk] % p, p - 2, p) % p;
n /= p, k /= p;
}
return ret;
} ll multi_mod(ll a, ll b, ll p) { //a * b % p
a = (a % p + p) % p;
b = (b % p + p) % p;
ll ret = 0;
while (b) {
if (b & 1) {
ret += a;
if (ret >= p) ret -= p;
}
b >>= 1;
a <<= 1;
if (a >= p) a -= p;
}
return ret;
} ll ex_GCD(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1; y = 0; return a;
}
ll d = ex_GCD (b, a % b, y, x);
y -= x * (a / b);
return d;
} ll China(int k, ll *b, ll *m) {
ll M = 1, x, y, ret = 0;
for (int i=1; i<=k; ++i) M *= m[i];
for (int i=1; i<=k; ++i) {
ll w = M / m[i];
ex_GCD (w, m[i], x, y);
ret += multi_mod (multi_mod (x, w, M), b[i], M);
}
return (ret + M) % M;
} int main(void) {
int T; scanf ("%d", &T);
while (T--) {
ll p[11], b[11];
ll n, m; int k; scanf ("%I64d%I64d%d", &n, &m, &k);
for (int i=1; i<=k; ++i) {
scanf ("%I64d", &p[i]); init (p[i]);
b[i] = Lucas (n, m, p[i]);
}
printf ("%I64d\n", China (k, b, p));
} return 0;
}
最新文章
- locky勒索样本分析
- 关于采用github.io搭建个人博客
- Unity 3D 中实现对物体 位置(position) 旋转(rotation) 大小(scale) 的全面控制
- 处理html5离线应用程序存储的一些问题。
- VISO下载地址
- TFS 2010 使用手册(二)项目集合与项目
- <;a href=";javascript:void(0);"; id=&#39;test&#39; onclick=";javascript:alert(&#39;即将上线,敬请期待!&#39;);";>;<;em class=";rmwd";>;<;/em>;征稿平台<;/a>;
- 第七篇、使用UIView的animateWithDuration方法制作简易动画
- 离线安装maven
- <;有序数组>;转化为<;按二分法遍历顺序排列的数组>;(C++实现)
- 201521123009《Java程序设计》第14周学习总结
- C#应用程序隐藏调用bat脚本
- java 根据ip获取地区信息(淘宝和新浪)
- 微信小程序开发-tabbar组件
- django 开发笔记1
- ckeditor_学习(2) 功能概览
- python-简单的登陆接口
- 编译安装Python3
- Asp.net core WebApi 使用Swagger生成帮助页实例
- 8.1 shell介绍 8.2 命令历史 8.3 命令补全和别名 8.4 通配符 8.5 输入输出重定向
热门文章
- JAVA变量存储
- Hadoop中序列化与Writable接口
- 51Nod 1282 时钟 —— 最小表示法 + 字符串哈希
- AndroidStudio——Android SDK
- 解决 git branch -a 无法全部显示远程的分支,只显示master分支
- wukong引擎源码分析之索引——part 1 倒排列表本质是有序数组存储
- codeforces 690C1 C1. Brain Network (easy)(水题)
- xcode 修改类名 变量名
- SPOJ:Lexicographically Smallest(并查集&;排序)
- SPOJ:Free tour II (树分治+启发式合并)