您的位置:首页 > 理论基础 > 计算机网络

HDU 5446 Unknown Treasure (2015年长春赛区网络赛J题)

2015-09-13 16:33 706 查看
1.题目描述:点击打开链接

2.解题思路:本题利用Lucas+CRT+移位乘法解决。然而。。。比赛时候意识到了可能会爆long long,但是还没学移位乘法,受到了100点伤害==

3.代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<complex>
#include<functional>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define me(s)  memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair <int, int> P;

ll n, m;
int k;
int primes[12];
int a[12];
ll pow_mod(ll a, ll n, ll p)
{
	ll res = 1;
	while (n>0)
	{
		if (n & 1)res = res*a%p;
		a = a*a%p;
		n >>= 1;
	}
	return res;
}

void gcd(ll a, ll b, ll&d, ll&x, ll&y)
{
	if (!b) { x = 1, y = 0, d = a; }
	else
	{
		gcd(b, a%b, d, y, x);
		y -= x*(a / b);
	}
}

ll C(ll n, ll m, int p)
{
	if (m>n)return 0;
	ll t1 = 1, t2 = 1;
	for (int i = n; i>m; i--)
	{
		t1 = (t1*i) % p;
		t2 = (t2*(i - m)) % p;
	}
	return (t1%p)*(pow_mod(t2, p - 2, p) % p) % p;
}

ll Lucas(ll n, ll m, int p)
{
	if (!m)return 1;
	ll ans = C(n%p, m%p, p);
	return ans*Lucas(n / p, m / p, p) % p;
}

ll M;

ll mul(ll a, ll b, ll p)
{
	ll res = 0;
	for (; a; a >>= 1)
	{
		if (a & 1)
		{
			res += b;
			if (res >= p)res -= p;
		}
		b <<= 1;
		if (b >= p)b -= p;
	}
	return res;
}

ll China(int n, int*a, int*m)
{
	M = 1;
	for (int i = 0; i<n; i++)
		M *= m[i];
	ll x = 0, d, y;
	for (int i = 0; i<n; i++)
	{
		ll w = M / m[i];
		gcd((ll)m[i], w, d, d, y);
		int sign;
		if (y < 0)sign = -1;
		else sign = 1;
		x = (x + mul(y*sign, w*a[i] % M, M)*sign) % M;
	}
	return (x + M) % M;
}

int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		cin >> n >> m >> k;
		for (int i = 0; i<k; i++)
			cin >> primes[i];
		for (int i = 0; i<k; i++)
			a[i] = Lucas(n, m, primes[i]);
		ll ans = China(k, a, primes);
		printf("%I64d\n", ans);
	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: