hdu 5446 Unknown Treasure(lucas+中国剩余定理)
2015-09-13 21:59
399 查看
题目链接:hdu 5446 Unknown Treasure
lucas+中国剩余定理裸题,注意在中国剩余定理里面,有可能两数相乘爆long long,要用按位乘的方式,但是这样的话exgcd返回值如果是负数就会出错,所以乘之前要取模成正的。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
ll fac[maxn], inv[maxn];
ll pow_mod(ll a, int n, int mod) {
ll ret = 1;
while (n) {
if (n&1) ret = ret * a % mod;
a = a * a % mod;
n >>= 1;
}
return ret;
}
void init(int n) {
fac[0] = 1;
for (int i = 1; i < n; i++) fac[i] = fac[i-1] * i % n;
inv[n-1] = pow_mod(fac[n-1], n-2, n);
for (int i = n - 2; i >= 0; i--) inv[i] = inv[i+1] * (i+1) % n;
}
ll C (int n, int m, int mod) {
if (m > n || m < 0 || n < 0) return 0;
return fac
* inv[m] % mod * inv[n-m] % mod;
}
ll lucas(ll n, ll m, int mod) {
if (m == 0) return 1;
return lucas(n / mod, m / mod, mod) * C(n % mod, m % mod, mod) % mod;
}
ll exgcd(ll a, ll b, ll& x, ll& y) {
if (b == 0) { x = 1; y = 0; return a; }
ll d = exgcd(b, a % b, y, x);
y -= x * (a / b);
return d;
}
ll mul(ll a, ll b, ll mod) {
a = (a % mod + mod) % mod;
b = (b % mod + mod) % mod;
ll ret = 0;
while(b){
if(b&1){
ret += a;
if(ret >= mod) ret -= mod;
}
b >>= 1;
a <<= 1;
if(a >= mod) a -= mod;
}
return ret;
}
ll china(int n, ll* a, ll* m) {
ll M = 1, d, y, x = 0;
for (int i = 0; i < n; i++) M *= m[i];
for (int i = 0; i < n; i++) {
ll w = M / m[i];
exgcd(m[i], w, d, y);
x = (x + mul(mul(y, w, M), a[i], M));
}
return (x + M) % M;
}
int main () {
int cas, k;
ll n, m, a[15], p[15];
scanf("%d", &cas);
while (cas--) {
scanf("%lld%lld%d", &n, &m, &k);
for (int i = 0; i < k; i++) {
scanf("%lld", &p[i]);
init(p[i]);
a[i] = lucas(n, m, p[i]);
}
printf("%lld\n", china(k, a, p));
}
return 0;
}
lucas+中国剩余定理裸题,注意在中国剩余定理里面,有可能两数相乘爆long long,要用按位乘的方式,但是这样的话exgcd返回值如果是负数就会出错,所以乘之前要取模成正的。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
ll fac[maxn], inv[maxn];
ll pow_mod(ll a, int n, int mod) {
ll ret = 1;
while (n) {
if (n&1) ret = ret * a % mod;
a = a * a % mod;
n >>= 1;
}
return ret;
}
void init(int n) {
fac[0] = 1;
for (int i = 1; i < n; i++) fac[i] = fac[i-1] * i % n;
inv[n-1] = pow_mod(fac[n-1], n-2, n);
for (int i = n - 2; i >= 0; i--) inv[i] = inv[i+1] * (i+1) % n;
}
ll C (int n, int m, int mod) {
if (m > n || m < 0 || n < 0) return 0;
return fac
* inv[m] % mod * inv[n-m] % mod;
}
ll lucas(ll n, ll m, int mod) {
if (m == 0) return 1;
return lucas(n / mod, m / mod, mod) * C(n % mod, m % mod, mod) % mod;
}
ll exgcd(ll a, ll b, ll& x, ll& y) {
if (b == 0) { x = 1; y = 0; return a; }
ll d = exgcd(b, a % b, y, x);
y -= x * (a / b);
return d;
}
ll mul(ll a, ll b, ll mod) {
a = (a % mod + mod) % mod;
b = (b % mod + mod) % mod;
ll ret = 0;
while(b){
if(b&1){
ret += a;
if(ret >= mod) ret -= mod;
}
b >>= 1;
a <<= 1;
if(a >= mod) a -= mod;
}
return ret;
}
ll china(int n, ll* a, ll* m) {
ll M = 1, d, y, x = 0;
for (int i = 0; i < n; i++) M *= m[i];
for (int i = 0; i < n; i++) {
ll w = M / m[i];
exgcd(m[i], w, d, y);
x = (x + mul(mul(y, w, M), a[i], M));
}
return (x + M) % M;
}
int main () {
int cas, k;
ll n, m, a[15], p[15];
scanf("%d", &cas);
while (cas--) {
scanf("%lld%lld%d", &n, &m, &k);
for (int i = 0; i < k; i++) {
scanf("%lld", &p[i]);
init(p[i]);
a[i] = lucas(n, m, p[i]);
}
printf("%lld\n", china(k, a, p));
}
return 0;
}
相关文章推荐
- 只要肯用脑子,就不是简单的重复(拥抱重复,发现规律,发现价值,一万小时的基础)
- 面向对象设计原则
- JS BOM(浏览器对象)
- unpipc.h下载和编译
- iOS之OC随笔-Model数据类型
- iOS软件开发 获取相册图片或照相
- 数据结构学习2--线性表的设计与实现(二)
- UNIX 高手的 10 个习惯 http://www.ibm.com/developerworks/cn/aix/library/au-badunixhabits.html
- RadialGradient环形渲染
- 虚数的图解
- 重拾java系列一java基础(3)
- Python进阶06 循环对象
- 每天一个linux命令(4):mkdir命令 http://www.cnblogs.com/younes/archive/2009/11/20/1607174.html
- Linux ELF File
- Unity Web Player修改加载页面的LOGO
- JavaScript设计模式——单体模式
- hdu 5444 Elven Postman(二叉树)
- 网页的加载渲染速度分析及网页支持程度和兼容性
- Git之添加远程库
- 实现跨平台的C++线程库