• 【LG2183】[国家集训队]礼物


    【LG2183】[国家集训队]礼物

    题面

    洛谷

    题解

    插曲:不知道为什么,一看到这个题目,我就想到了这个人。。。

    如果不是有(exLucas),这题就是(sb)题。。。

    首先,若(sum_{i=1}^mw_i>n)就直接(Impossible)

    然后我们考虑怎么求方案,其实很简单啊。。。

    就是

    [ans=prod_{i=1}^m(n-sum_{j=1}^{i-1}w_j) ]

    因为模数小,要用(exLucas)

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring> 
    #include <cmath> 
    #include <algorithm>
    using namespace std; 
    typedef long long ll; 
    ll exgcd(ll a, ll b, ll &x, ll &y) {
    	if (!b) return x = 1, y = 0, a; 
    	ll res = exgcd(b, a % b, x, y), t;
    	t = x, x = y, y = t - a / b * y; 
    	return res; 
    } 
    ll fpow(ll x, ll y, ll Mod) { 
    	ll res = 1; 
    	while (y) { 
    		if (y & 1ll) res = res * x % Mod; 
    		x = x * x % Mod; 
    		y >>= 1ll; 
    	}
    	return res; 
    } 
    ll fac(ll n, ll pi, ll pk) { 
    	if (!n) return 1; 
    	ll res = 1; 
    	for (ll i = 2; i <= pk; i++) 
    		if (i % pi) res = res * i % pk; 
    	res = fpow(res, n / pk, pk); 
    	for (ll i = 2; i <= n % pk; i++) 
    		if (i % pi) res = res * i % pk; 
    	return res * fac(n / pi, pi, pk) % pk; 
    } 
    ll inv(ll n, ll Mod) { 
    	ll x, y;
    	exgcd(n, Mod, x, y); 
    	return (x + Mod) % Mod; 
    } 
    ll CRT(ll b, ll p, ll Mod) { return b * inv(p / Mod, Mod) % p * (p / Mod) % p; } 
    ll C(ll n, ll m, ll pi, ll pk) { 
    	ll fz = fac(n, pi, pk), fm1 = fac(m, pi, pk), fm2 = fac(n - m, pi, pk); 
    	ll k = 0; 
    	for (ll i = n; i; i /= pi) k += i / pi; 
    	for (ll i = m; i; i /= pi) k -= i / pi; 
    	for (ll i = n - m; i; i /= pi) k -= i / pi; 
    	return fz * inv(fm1, pk) % pk * inv(fm2, pk) % pk * fpow(pi, k, pk) % pk; 
    } 
    ll exlucas(ll n, ll m, ll Mod) { 
    	ll res = 0, tmp = Mod; 
    	for (int i = 2; 1ll * i * i <= Mod; i++)
    	    if (tmp % i == 0) { 
    		    ll pk = 1; while (tmp % i == 0) pk *= i, tmp /= i; 
    			res = (res + CRT(C(n, m, i, pk), Mod, pk)) % Mod; 
    	    } 
    	if (tmp > 1) res = (res + CRT(C(n, m, tmp, tmp), Mod, tmp)) % Mod;
    	return res; 
    }
    ll N, M, Mod;
    ll sum, w[10];
    
    int main () {
    	cin >> Mod >> N >> M; 
    	for (int i = 1; i <= M; i++) cin >> w[i], sum += w[i];
    	if (N < sum) return puts("Impossible") & 0; 
    	ll ans = 1; 
    	for (int i = 1; i <= M; i++) { 
    		ans = ans * exlucas(N, w[i], Mod) % Mod;
    		N -= w[i]; 
    	} 
    	printf("%lld
    ", ans); 
    	return 0; 
    } 
    
  • 相关阅读:
    (转载)林轩田机器学习基石课程学习笔记1 — The Learning Problem
    二、HDFS(架构、读写、NN)
    剑指:和为S的两个数字
    剑指:和为S的连续正数序列
    Hive:数据倾斜
    linux如何查看端口被哪个进程占用
    du查看某个文件或目录占用磁盘空间的大小
    剑指:滑动窗口的最大值
    leetcode之求众数
    剑指:重建二叉树
  • 原文地址:https://www.cnblogs.com/heyujun/p/10207226.html
Copyright © 2020-2023  润新知